Skip to content

Commit

Permalink
Merge pull request #2 from gemstone/SyncPhasorUpdatesFromGSF
Browse files Browse the repository at this point in the history
Synced updates from GSF.PhasorProtocols
  • Loading branch information
clackner-gpa authored Feb 19, 2024
2 parents bc1f9e4 + 417b7a0 commit c1d2fa9
Show file tree
Hide file tree
Showing 21 changed files with 195 additions and 35 deletions.
7 changes: 5 additions & 2 deletions src/Gemstone.PhasorProtocols/Anonymous/ConfigurationFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,13 @@ private static void CacheConfigurationFile(Tuple<IConfigurationFrame, Action<Exc
/// </summary>
/// <param name="configurationName">Name of the configuration to get file name for.</param>
/// <returns>File name with path of the specified <paramref name="configurationName"/>.</returns>
public static string GetConfigurationCacheFileName(string configurationName)
public static string GetConfigurationCacheFileName(string configurationName, string extension = "configuration.xml", string basePath = null)
{
// Path traversal attacks are prevented by replacing invalid file name characters
return $"{ConfigurationCachePath}{configurationName.ReplaceCharacters('_', c => Path.GetInvalidFileNameChars().Contains(c))}.configuration.xml";
return $"{basePath ?? ConfigurationCachePath}{RemoveInvalidCharacters(configurationName)}.{RemoveInvalidCharacters(extension)}";

static string RemoveInvalidCharacters(string name) =>
name.ReplaceCharacters('_', c => Path.GetInvalidFileNameChars().Contains(c));
}

/// <summary>
Expand Down
11 changes: 11 additions & 0 deletions src/Gemstone.PhasorProtocols/IEC61850_90_5/CommandFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ protected CommandFrame(SerializationInfo info, StreamingContext context)
{
// Deserialize command frame
m_frameHeader = (CommonFrameHeader)info.GetValue("frameHeader", typeof(CommonFrameHeader));
m_frameHeader.Timestamp = base.Timestamp;
m_frameHeader.IDCode = base.IDCode;
}

#endregion
Expand Down Expand Up @@ -158,6 +160,15 @@ public override Ticks Timestamp
base.Timestamp = value;
}
}
public override ushort IDCode
{
get => CommonHeader.IDCode;
set
{
CommonHeader.IDCode = value;
base.IDCode = value;
}
}

/// <summary>
/// Gets the IEC 61850-90-5 protocol version of this <see cref="CommandFrame"/>.
Expand Down
11 changes: 11 additions & 0 deletions src/Gemstone.PhasorProtocols/IEC61850_90_5/ConfigurationFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ protected ConfigurationFrame(SerializationInfo info, StreamingContext context)
// Deserialize configuration frame
m_frameHeader = (CommonFrameHeader)info.GetValue("frameHeader", typeof(CommonFrameHeader));
m_timebase = info.GetUInt32("timebase");
m_frameHeader.Timestamp = base.Timestamp;
m_frameHeader.IDCode = base.IDCode;
}

#endregion
Expand Down Expand Up @@ -129,6 +131,15 @@ public override Ticks Timestamp
base.Timestamp = value;
}
}
public override ushort IDCode
{
get => CommonHeader.IDCode;
set
{
CommonHeader.IDCode = value;
base.IDCode = value;
}
}

/// <summary>
/// Gets or sets current <see cref="CommonFrameHeader"/>.
Expand Down
7 changes: 7 additions & 0 deletions src/Gemstone.PhasorProtocols/IEC61850_90_5/DataFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ protected DataFrame(SerializationInfo info, StreamingContext context)
m_configurationRevision = info.GetUInt32("configurationRevision");
SampleSynchronization = info.GetByte("sampleSynchronization");
m_sampleRate = info.GetUInt16("sampleRate");
m_frameHeader.Timestamp = base.Timestamp;
m_frameHeader.IDCode = base.IDCode;
}

#endregion
Expand Down Expand Up @@ -178,6 +180,11 @@ public override Ticks Timestamp
base.Timestamp = value;
}
}
public override ushort IDCode
{
get => CommonHeader.IDCode;
set => CommonHeader.IDCode = value;
}

/// <summary>
/// Gets the identifier that is used to identify the IEC 61850-90-5 frame.
Expand Down
4 changes: 2 additions & 2 deletions src/Gemstone.PhasorProtocols/IEEE1344/CommandFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public CommandFrame(byte[] buffer, int startIndex, int length)
public CommandFrame(ulong idCode, DeviceCommand command)
: base(new CommandCellCollection(0), command)
{
m_idCode = idCode;
IDCode = idCode;
Timestamp = DateTime.UtcNow.Ticks;
}

Expand All @@ -111,7 +111,7 @@ protected CommandFrame(SerializationInfo info, StreamingContext context)
: base(info, context)
{
// Deserialize command frame
m_idCode = info.GetUInt64("idCode64Bit");
IDCode = info.GetUInt64("idCode64Bit");
}

#endregion
Expand Down
5 changes: 4 additions & 1 deletion src/Gemstone.PhasorProtocols/IEEE1344/ConfigurationFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ protected ConfigurationFrame(SerializationInfo info, StreamingContext context)
{
// Deserialize configuration frame
m_frameHeader = (CommonFrameHeader)info.GetValue("frameHeader", typeof(CommonFrameHeader));
m_idCode = info.GetUInt64("idCode64Bit");
IDCode = info.GetUInt64("idCode64Bit");

// Copy in associated properties from base class deserialization that are proxied for use by CommonFrameHeader
m_frameHeader.Timestamp = base.Timestamp;
}

#endregion
Expand Down
3 changes: 3 additions & 0 deletions src/Gemstone.PhasorProtocols/IEEE1344/DataFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ protected DataFrame(SerializationInfo info, StreamingContext context)
{
// Deserialize data frame
m_frameHeader = (CommonFrameHeader)info.GetValue("frameHeader", typeof(CommonFrameHeader));

// Copy in associated properties from base class deserialization that are proxied for use by CommonFrameHeader
m_frameHeader.Timestamp = base.Timestamp;
}

#endregion
Expand Down
5 changes: 4 additions & 1 deletion src/Gemstone.PhasorProtocols/IEEE1344/HeaderFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ protected HeaderFrame(SerializationInfo info, StreamingContext context)
{
// Deserialize header frame
m_frameHeader = (CommonFrameHeader)info.GetValue("frameHeader", typeof(CommonFrameHeader));
m_idCode = info.GetUInt64("idCode64Bit");
IDCode = info.GetUInt64("idCode64Bit");

// Copy in associated properties from base class deserialization that are proxied for use by CommonFrameHeader
m_frameHeader.Timestamp = base.Timestamp;
}

#endregion
Expand Down
32 changes: 31 additions & 1 deletion src/Gemstone.PhasorProtocols/IEEEC37_118/AnalogValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
//******************************************************************************************************

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace Gemstone.PhasorProtocols.IEEEC37_118
Expand Down Expand Up @@ -91,6 +92,35 @@ protected AnalogValue(SerializationInfo info, StreamingContext context)
set => base.Definition = value;
}

/// <summary>
/// Gets or sets the <see cref="AnalogDefinition3"/> associated with this <see cref="AnalogValue"/>.
/// </summary>
public virtual AnalogDefinition3 Definition3
{
get => base.Definition as AnalogDefinition3;
set => base.Definition = value;
}

/// <summary>
/// <see cref="Dictionary{TKey,TValue}"/> of string based property names and values for the <see cref="AnalogValueBase"/> object.
/// </summary>
public override Dictionary<string, string> Attributes
{
get
{
AnalogDefinition3 definition3 = Definition3;

if (definition3 is null)
return base.Attributes;

Dictionary<string, string> baseAttributes = base.Attributes;

baseAttributes.Add("Analog Value Scaled", $"{Value * definition3.Multiplier + definition3.Adder}");

return baseAttributes;
}
}

#endregion

#region [ Static ]
Expand All @@ -109,4 +139,4 @@ internal static IAnalogValue CreateNewValue(IDataCell parent, IAnalogDefinition

#endregion
}
}
}
18 changes: 18 additions & 0 deletions src/Gemstone.PhasorProtocols/IEEEC37_118/CommandFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ protected CommandFrame(SerializationInfo info, StreamingContext context)
{
// Deserialize command frame
m_frameHeader = (CommonFrameHeader)info.GetValue("frameHeader", typeof(CommonFrameHeader));

// Copy in associated properties from base class deserialization that are proxied for use by CommonFrameHeader
m_frameHeader.Timestamp = base.Timestamp;
m_frameHeader.IDCode = base.IDCode;
}

#endregion
Expand Down Expand Up @@ -161,6 +165,20 @@ public override Ticks Timestamp
}
}

/// <summary>
/// Gets or sets the ID code.
/// </summary>
public override ushort IDCode
{
get => CommonHeader.IDCode;
set
{
// Keep ID code updates synchronized...
CommonHeader.IDCode = value;
base.IDCode = value;
}
}

/// <summary>
/// Gets the IEEE C37.118 protocol version of this <see cref="CommandFrame"/>.
/// </summary>
Expand Down
40 changes: 23 additions & 17 deletions src/Gemstone.PhasorProtocols/IEEEC37_118/ConfigurationFrame1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ public class ConfigurationFrame1 : ConfigurationFrameBase, ISupportSourceIdentif
// Fields
private CommonFrameHeader m_frameHeader;

/// <summary>
/// Represents the TimeBase of the configuration frame.
/// </summary>
protected uint m_timebase;

#endregion

#region [ Constructors ]
Expand Down Expand Up @@ -98,7 +93,10 @@ protected ConfigurationFrame1(SerializationInfo info, StreamingContext context)
{
// Deserialize configuration frame
m_frameHeader = (CommonFrameHeader)info.GetValue("frameHeader", typeof(CommonFrameHeader));
m_timebase = info.GetUInt32("timebase");

// Copy in associated properties from base class deserialization that are proxied for use by CommonFrameHeader
m_frameHeader.Timestamp = base.Timestamp;
m_frameHeader.IDCode = base.IDCode;
}

#endregion
Expand Down Expand Up @@ -137,6 +135,20 @@ public override Ticks Timestamp
}
}

/// <summary>
/// Gets or sets the ID code.
/// </summary>
public override ushort IDCode
{
get => CommonHeader.IDCode;
set
{
// Keep ID code updates synchronized...
CommonHeader.IDCode = value;
base.IDCode = value;
}
}

/// <summary>
/// Gets or sets current <see cref="CommonFrameHeader"/>.
/// </summary>
Expand All @@ -154,7 +166,6 @@ public CommonFrameHeader CommonHeader
State = m_frameHeader.State as IConfigurationFrameParsingState;
base.IDCode = m_frameHeader.IDCode;
base.Timestamp = m_frameHeader.Timestamp;
m_timebase = m_frameHeader.Timebase;
}
}

Expand All @@ -179,12 +190,8 @@ public byte Version
/// </summary>
public uint Timebase
{
get => m_timebase;
set
{
m_timebase = value & ~Common.TimeQualityFlagsMask;
CommonHeader.Timebase = m_timebase;
}
get => CommonHeader.Timebase;
set => CommonHeader.Timebase = value & ~Common.TimeQualityFlagsMask;
}

/// <summary>
Expand Down Expand Up @@ -227,7 +234,7 @@ protected override byte[] HeaderImage
int index = 0;

CommonHeader.BinaryImage.CopyImage(buffer, ref index, CommonFrameHeader.FixedLength);
BigEndian.CopyBytes(m_timebase, buffer, index);
BigEndian.CopyBytes(CommonHeader.Timebase, buffer, index);
BigEndian.CopyBytes((ushort)Cells.Count, buffer, index + 4);

return buffer;
Expand Down Expand Up @@ -298,8 +305,7 @@ protected override int ParseHeaderImage(byte[] buffer, int startIndex, int lengt
// Skip past header that was already parsed...
startIndex += CommonFrameHeader.FixedLength;

m_timebase = BigEndian.ToUInt32(buffer, startIndex) & ~Common.TimeQualityFlagsMask;
CommonHeader.Timebase = m_timebase;
CommonHeader.Timebase = BigEndian.ToUInt32(buffer, startIndex) & ~Common.TimeQualityFlagsMask;
State.CellCount = BigEndian.ToUInt16(buffer, startIndex + 4);

return FixedHeaderLength;
Expand Down Expand Up @@ -342,7 +348,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont

// Serialize configuration frame
info.AddValue("frameHeader", m_frameHeader, typeof(CommonFrameHeader));
info.AddValue("timebase", m_timebase);
info.AddValue("timebase", m_frameHeader.Timebase);
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ protected override byte[] HeaderImage

CommonHeader.BinaryImage.CopyImage(buffer, ref index, CommonFrameHeader.FixedLength);
BigEndian.CopyBytes((ushort)0, buffer, index); // CONT_IDX
BigEndian.CopyBytes(m_timebase, buffer, index + 2);
BigEndian.CopyBytes(Timebase, buffer, index + 2);
BigEndian.CopyBytes((ushort)Cells.Count, buffer, index + 6);

return buffer;
Expand Down Expand Up @@ -301,8 +301,7 @@ protected override int ParseHeaderImage(byte[] buffer, int startIndex, int lengt
// Skip past header that was already parsed...
startIndex += FrameHeaderLength; // Includes CONT_IDX

m_timebase = BigEndian.ToUInt32(buffer, startIndex) & ~Common.TimeQualityFlagsMask;
CommonHeader.Timebase = m_timebase;
Timebase = BigEndian.ToUInt32(buffer, startIndex) & ~Common.TimeQualityFlagsMask;
State.CellCount = BigEndian.ToUInt16(buffer, startIndex + 4);

return FixedHeaderLength;
Expand Down
14 changes: 14 additions & 0 deletions src/Gemstone.PhasorProtocols/IEEEC37_118/DataFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ protected DataFrame(SerializationInfo info, StreamingContext context)
{
// Deserialize data frame
m_frameHeader = (CommonFrameHeader)info.GetValue("frameHeader", typeof(CommonFrameHeader));

// Copy in associated properties from base class deserialization that are proxied for use by CommonFrameHeader
m_frameHeader.Timestamp = base.Timestamp;
m_frameHeader.IDCode = base.IDCode;
}

#endregion
Expand Down Expand Up @@ -125,6 +129,16 @@ public override Ticks Timestamp
}
}

/// <summary>
/// Gets or sets the ID code.
/// </summary>
public override ushort IDCode
{
get => CommonHeader.IDCode;
// Keep ID code updates synchronized...
set => CommonHeader.IDCode = value;
}

/// <summary>
/// Gets the identifier that is used to identify the IEEE C37.118 frame.
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions src/Gemstone.PhasorProtocols/IEEEC37_118/FrameParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -386,13 +386,13 @@ protected override void OnReceivedChannelFrame(IChannelFrame frame)
ReceivedDataFrame?.SafeInvoke(this, new EventArgs<DataFrame>(dataFrame));
break;
}
// Configuration frame type 3 has priority over type 2, so we check it first
// Configuration frame type 3 is more specific than type 1 (and more common), so we check it first
case ConfigurationFrame3 configFrame3:
{
ReceivedConfigurationFrame3?.SafeInvoke(this, new EventArgs<ConfigurationFrame3>(configFrame3));
break;
}
// Configuration frame type 2 is more specific than type 1 (and more common), so we check it next
// Configuration frame type 2 is more specific than type 1 (and more common), so we check it first
case ConfigurationFrame2 configFrame2:
{
ReceivedConfigurationFrame2?.SafeInvoke(this, new EventArgs<ConfigurationFrame2>(configFrame2));
Expand Down
Loading

0 comments on commit c1d2fa9

Please sign in to comment.