diff --git a/src/.idea/.idea.L5Sharp/.idea/workspace.xml b/src/.idea/.idea.L5Sharp/.idea/workspace.xml
index 382b6003..049bc682 100644
--- a/src/.idea/.idea.L5Sharp/.idea/workspace.xml
+++ b/src/.idea/.idea.L5Sharp/.idea/workspace.xml
@@ -8,16 +8,32 @@
-
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -380,7 +392,11 @@
-
+
+
+
+
+ 1677621948966
@@ -725,7 +741,7 @@
1687451515386
-
+
@@ -735,7 +751,7 @@
-
+
@@ -761,9 +777,6 @@
-
-
-
@@ -786,7 +799,10 @@
-
+
+
+
+
@@ -797,19 +813,6 @@
-
- file://$PROJECT_DIR$/../tests/L5Sharp.Tests/LogixParserTests.cs
- 196
-
-
-
-
-
-
-
-
-
-
diff --git a/src/L5Sharp.Core/Components/AddOnInstruction.cs b/src/L5Sharp.Core/Components/AddOnInstruction.cs
index 0f41d70c..fd843d7f 100644
--- a/src/L5Sharp.Core/Components/AddOnInstruction.cs
+++ b/src/L5Sharp.Core/Components/AddOnInstruction.cs
@@ -46,6 +46,19 @@ public AddOnInstruction() : base(new XElement(L5XName.AddOnInstructionDefinition
public AddOnInstruction(XElement element) : base(element)
{
}
+
+ ///
+ /// The value indicating whether this component is a standard or safety type component.
+ ///
+ /// A option representing class of the component.
+ ///
+ /// Specify the class of the Add-On Instruction. This attribute applies only to safety controller projects.
+ ///
+ public ComponentClass? Class
+ {
+ get => GetValue();
+ set => SetValue(value);
+ }
///
/// The revision of the instruction.
diff --git a/src/L5Sharp.Core/Components/Program.cs b/src/L5Sharp.Core/Components/Program.cs
index 282eb003..fa0c8ae4 100644
--- a/src/L5Sharp.Core/Components/Program.cs
+++ b/src/L5Sharp.Core/Components/Program.cs
@@ -49,6 +49,20 @@ public ProgramType Type
get => GetValue() ?? ProgramType.Normal;
set => SetValue(value);
}
+
+ ///
+ /// The value indicating whether this component is a standard or safety type component.
+ ///
+ /// A option representing class of the component.
+ ///
+ /// Specify the class of the program. This attribute applies only to safety controller projects.
+ /// Do not use this attribute if the program is an Equipment Phase program.
+ ///
+ public ComponentClass? Class
+ {
+ get => GetValue();
+ set => SetValue(value);
+ }
///
/// The value indicating whether the program has current test edits pending.
diff --git a/src/L5Sharp.Core/Components/Tag.cs b/src/L5Sharp.Core/Components/Tag.cs
index a3fc71e6..4c882437 100644
--- a/src/L5Sharp.Core/Components/Tag.cs
+++ b/src/L5Sharp.Core/Components/Tag.cs
@@ -174,6 +174,17 @@ public ExternalAccess? ExternalAccess
set => SetValue(value);
}
+ ///
+ /// The value indicating whether this component is a standard or safety type component.
+ ///
+ /// A option representing class of the component.
+ /// Specify the class of the tag. This attribute applies only to safety controller projects.
+ public ComponentClass? Class
+ {
+ get => GetValue();
+ set => SetValue(value);
+ }
+
///
/// A type indicating whether the current tag component is a base tag, or alias for another tag instance.
///
@@ -214,7 +225,7 @@ public bool? Constant
get => GetValue();
set => SetValue(value);
}
-
+
///
/// The defining the configuration for a produced tag.
///
@@ -228,7 +239,7 @@ public ProduceInfo? ProduceInfo
get => GetComplex();
set => SetComplex(value);
}
-
+
///
/// The defining the configuration for a consumed tag.
///
@@ -330,7 +341,7 @@ public Tag this[TagName tagName]
return remaining.IsEmpty ? tag : tag[remaining];
}
}
-
+
///
/// Adds a new member to the tag's complex data structure.
///
@@ -481,8 +492,8 @@ public IEnumerable MembersOf(TagName tagName)
/// The logix data type of the tag. Type must have parameterless constructor to create.
/// A new object with specified parameters.
public static Tag New(string name) where TLogixType : LogixType, new() =>
- new() {Name = name, Value = new TLogixType()};
-
+ new() { Name = name, Value = new TLogixType() };
+
///
/// Removes a member with the specified name from the tag's complex data structure.
///
@@ -499,7 +510,7 @@ public void Remove(string name)
throw new InvalidOperationException("Can only mutate ComplexType tags.");
complexType.Remove(name);
}
-
+
///
/// Returns a collection of all descendent tag names of the current Tag, including the tag name of the
/// this Tag.
diff --git a/src/L5Sharp.Core/Components/Task.cs b/src/L5Sharp.Core/Components/Task.cs
index 29c15df7..3e62b91c 100644
--- a/src/L5Sharp.Core/Components/Task.cs
+++ b/src/L5Sharp.Core/Components/Task.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
+using JetBrains.Annotations;
namespace L5Sharp.Core;
@@ -20,6 +21,7 @@ namespace L5Sharp.Core;
/// See
/// `Logix 5000 Controllers Import/Export` for more information.
///
+[PublicAPI]
public class Task : LogixComponent
{
///
@@ -56,6 +58,19 @@ public TaskType Type
set => SetRequiredValue(value);
}
+ ///
+ /// The value indicating whether this component is a standard or safety type component.
+ ///
+ /// A option representing class of the component.
+ ///
+ /// Specify the class of the task. This attribute applies only to safety controller projects.
+ ///
+ public ComponentClass? Class
+ {
+ get => GetValue();
+ set => SetValue(value);
+ }
+
///
/// The scan priority of the task component. Default of 10.
///
@@ -117,7 +132,7 @@ public TaskEventTrigger? EventTrigger
get => GetValue(L5XName.EventInfo.XName());
set => SetValue(value, L5XName.EventInfo.XName());
}
-
+
///
/// The tag name that the event task consumes. Only used for event tasks.
///
@@ -130,7 +145,7 @@ public TagName? EventTag
get => GetValue(L5XName.EventInfo.XName());
set => SetValue(value, L5XName.EventInfo.XName());
}
-
+
///
/// The value indicating whether timeouts are enabled for the event task. Only used for event tasks.
///
@@ -175,12 +190,12 @@ public override L5X Export(Revision? softwareRevision = null)
public override void Delete()
{
if (Element.Parent is null || !IsAttached) return;
-
+
foreach (var program in Programs)
{
program.Delete();
}
-
+
Element.Remove();
}
diff --git a/src/L5Sharp.Core/Enums/ComponentClass.cs b/src/L5Sharp.Core/Enums/ComponentClass.cs
new file mode 100644
index 00000000..b246eda0
--- /dev/null
+++ b/src/L5Sharp.Core/Enums/ComponentClass.cs
@@ -0,0 +1,21 @@
+namespace L5Sharp.Core;
+
+///
+/// An enumeration of all for a various components.
+///
+public class ComponentClass : LogixEnum
+{
+ private ComponentClass(string name, string value) : base(name, value)
+ {
+ }
+
+ ///
+ /// Represents a Standard value.
+ ///
+ public static readonly ComponentClass Standard = new(nameof(Standard), nameof(Standard));
+
+ ///
+ /// Represents a Safety value.
+ ///
+ public static readonly ComponentClass Safety = new(nameof(Safety), nameof(Safety));
+}
\ No newline at end of file
diff --git a/src/L5Sharp.Core/L5Sharp.Core.csproj b/src/L5Sharp.Core/L5Sharp.Core.csproj
index a03c0c16..c9965db8 100644
--- a/src/L5Sharp.Core/L5Sharp.Core.csproj
+++ b/src/L5Sharp.Core/L5Sharp.Core.csproj
@@ -7,9 +7,9 @@
trueL5SharpTimothy Nunnink
- 0.19.4
- 0.19.4
- 0.19.4.0
+ 0.19.5
+ 0.19.5
+ 0.19.5.0A library for intuitively interacting with Rockwell's L5X import/export files.https://github.com/tnunnink/L5Sharpcsharp allen-bradely l5x logix plc-programming rockwell-automation logix5000
@@ -17,7 +17,7 @@
MITgit
- Bug fix to the LogixParser.cs TryParse
+ Added ComponentClass enum to component classes.Copyright (c) Timothy Nunnink 2022README.mdL5Sharp
diff --git a/src/L5Sharp.Core/LogixElement.cs b/src/L5Sharp.Core/LogixElement.cs
index e0fb9e6d..8ed9493b 100644
--- a/src/L5Sharp.Core/LogixElement.cs
+++ b/src/L5Sharp.Core/LogixElement.cs
@@ -15,7 +15,7 @@ namespace L5Sharp.Core;
/// a single and pass it to the base constructor to be deserializable by the library.
///
[PublicAPI]
-public abstract class LogixElement : ILogixSerializable
+public abstract class LogixElement : ILogixSerializable, ILogixParsable
{
///
/// Creates a new default initialized with an having the
@@ -331,21 +331,20 @@ public void Replace(LogixElement element)
///
///
public virtual XElement Serialize() => Element;
+
+ ///
+ public static LogixElement Parse(string value)
+ {
+ var element = XElement.Parse(value);
+ return element.Deserialize();
+ }
- ///
- /// Determines if the provided is equivalent to this element in terms of both type and
- /// state, including all child elements and values.
- ///
- /// The to compare.
- /// ture if the elements are equivalent; Otherwise, false.
- ///
- /// This internally compares the underlying XML nodes of the two elements to determine if all their
- /// elements, attributes, and values are equal. This includes all nested or descendant elements (i.e. it
- /// compares the entire XML structure).
- ///
- public bool IsEquivalent(LogixElement other)
+ ///
+ public static LogixElement? TryParse(string? value)
{
- return XNode.DeepEquals(Element, other.Element);
+ if (string.IsNullOrEmpty(value)) return default;
+ var element = XElement.Parse(value);
+ return element.Deserialize();
}
///
diff --git a/src/L5Sharp.Core/LogixType.cs b/src/L5Sharp.Core/LogixType.cs
index e00ff2fc..38c16150 100644
--- a/src/L5Sharp.Core/LogixType.cs
+++ b/src/L5Sharp.Core/LogixType.cs
@@ -92,22 +92,6 @@ public override bool Equals(object? obj)
///
public override int GetHashCode() => Name.GetHashCode();
-
- ///
- /// Determines if the provided is equivalent to this type in terms of the underlying XML
- /// data that comprise the complex object.
- ///
- /// The to compare.
- /// ture if the types are equivalent; Otherwise, false.
- ///
- /// This internally compares the underlying XML nodes of the two types to determine if all their
- /// elements, attributes, and values are equal. This includes all nested or descendant elements (i.e. it
- /// compares the entire XML structure).
- ///
- public bool IsEquivalent(LogixType other)
- {
- return XNode.DeepEquals(Serialize(), other.Serialize());
- }
///
/// Gets a with the specified name if it exists for the ;
diff --git a/src/L5Sharp.Core/Utilities/L5XExtensions.cs b/src/L5Sharp.Core/Utilities/L5XExtensions.cs
index 174c0e32..4824ab52 100644
--- a/src/L5Sharp.Core/Utilities/L5XExtensions.cs
+++ b/src/L5Sharp.Core/Utilities/L5XExtensions.cs
@@ -37,7 +37,7 @@ public static Func Deserializer(this Type type)
throw new ArgumentException(
$"The type {type.Name} is not assignable (inherited) from '{typeof(TReturn).Name}'.");
- var constructor = type.GetConstructor(new[] { typeof(XElement) });
+ var constructor = type.GetConstructor([typeof(XElement)]);
if (constructor is null || !constructor.IsPublic)
throw new ArgumentException(
@@ -84,6 +84,23 @@ public static string Get(this XElement element, XName name) =>
public static bool IsEquivalent(this string value, string other) =>
StringComparer.OrdinalIgnoreCase.Equals(value, other);
+ ///
+ /// Determines if the provided object is structurally or deeply equal to another object by performing a compare
+ /// of the underlying XML data for the objects.
+ ///
+ /// This object to compare.
+ /// The other to compare.
+ /// ture if the objects are equivalent; Otherwise, false.
+ ///
+ /// This internally compares the underlying XML nodes of the two elements to determine if all their
+ /// elements, attributes, and values are equal. This includes all nested or descendant elements (i.e. it
+ /// compares the entire XML structure).
+ ///
+ public static bool IsEquivalent(this ILogixSerializable serializable, ILogixSerializable other)
+ {
+ return XNode.DeepEquals(serializable.Serialize(), other.Serialize());
+ }
+
///
/// Gets the L5X element name of the type's containing element.
///
diff --git a/tests/L5Sharp.Tests/Components/RoutineTests.cs b/tests/L5Sharp.Tests/Components/RoutineTests.cs
index 7c7b6261..ec0d280e 100644
--- a/tests/L5Sharp.Tests/Components/RoutineTests.cs
+++ b/tests/L5Sharp.Tests/Components/RoutineTests.cs
@@ -64,6 +64,4 @@ public void New_RungCollection_ShouldHaveExpectedCount()
routine.Content().Count().Should().Be(3);
}
-
-
}
\ No newline at end of file
diff --git a/tests/L5Sharp.Tests/Components/TagTests.Class_SetValidValue_ShouldBeVerified.verified.xml b/tests/L5Sharp.Tests/Components/TagTests.Class_SetValidValue_ShouldBeVerified.verified.xml
new file mode 100644
index 00000000..9771f17e
--- /dev/null
+++ b/tests/L5Sharp.Tests/Components/TagTests.Class_SetValidValue_ShouldBeVerified.verified.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/L5Sharp.Tests/Components/TagTests.cs b/tests/L5Sharp.Tests/Components/TagTests.cs
index f6b55496..5018c19b 100644
--- a/tests/L5Sharp.Tests/Components/TagTests.cs
+++ b/tests/L5Sharp.Tests/Components/TagTests.cs
@@ -889,4 +889,14 @@ public Task ConsumeInfo_SetNewValue_ShouldBeVerified()
}
#endregion
+
+ [Test]
+ public Task Class_SetValidValue_ShouldBeVerified()
+ {
+ var tag = new Tag { Name = "Test", Class = ComponentClass.Safety, Value = 100};
+
+ var xml = tag.Serialize().ToString();
+
+ return VerifyXml(xml);
+ }
}
\ No newline at end of file
diff --git a/tests/L5Sharp.Tests/L5Sharp.Tests.csproj b/tests/L5Sharp.Tests/L5Sharp.Tests.csproj
index 41cbb702..f19ec31f 100644
--- a/tests/L5Sharp.Tests/L5Sharp.Tests.csproj
+++ b/tests/L5Sharp.Tests/L5Sharp.Tests.csproj
@@ -292,6 +292,9 @@
TagTests.cs
+
+ TagTests.cs
+
diff --git a/tests/L5Sharp.Tests/LogixElementTests.cs b/tests/L5Sharp.Tests/LogixElementTests.cs
index aeeabfa8..c13510e9 100644
--- a/tests/L5Sharp.Tests/LogixElementTests.cs
+++ b/tests/L5Sharp.Tests/LogixElementTests.cs
@@ -956,12 +956,21 @@ public void Convert_AsTypeDefaultType_ShouldHaveExpectedTypeAndBeSameInstance()
converted.Should().BeSameAs(element);
}
+ /*[Test]
+ public void Parse_ValidXml_ShouldNotBeNull()
+ {
+
+ var element = LogixElement.Parse("");
+
+ element.Should().NotBeNull();
+ }*/
+
[Test]
public void IsEquivalent_AreEquivalent_ShouldBeTrue()
{
var first = new TestElement();
var second = new TestElement();
-
+
var result = first.IsEquivalent(second);
result.Should().BeTrue();
diff --git a/tests/L5Sharp.Tests/ProofTesting.cs b/tests/L5Sharp.Tests/ProofTesting.cs
index c8180422..a42ab1c9 100644
--- a/tests/L5Sharp.Tests/ProofTesting.cs
+++ b/tests/L5Sharp.Tests/ProofTesting.cs
@@ -52,10 +52,10 @@ public void Query()
public void ParserTypeTests()
{
var types = typeof(LogixParser).Assembly.GetTypes().Where(t =>
- t.GetInterfaces().Any(i =>
- i.IsGenericType &&
- i.GetGenericTypeDefinition() == typeof(ILogixParsable<>) &&
- i.GetGenericArguments().All(a => !a.IsGenericTypeParameter)))
+ t.GetInterfaces().Any(i =>
+ i.IsGenericType &&
+ i.GetGenericTypeDefinition() == typeof(ILogixParsable<>) &&
+ i.GetGenericArguments().All(a => !a.IsGenericTypeParameter)))
.ToList();
foreach (var type in types)
@@ -63,4 +63,4 @@ public void ParserTypeTests()
Console.WriteLine(type.FullName);
}
}
-}
+}
\ No newline at end of file