diff --git a/build/MTConnect.NET-SysML-Import/CSharp/MeasurementModel.cs b/build/MTConnect.NET-SysML-Import/CSharp/MeasurementModel.cs
index 54d8b47d2..8755c9a2e 100644
--- a/build/MTConnect.NET-SysML-Import/CSharp/MeasurementModel.cs
+++ b/build/MTConnect.NET-SysML-Import/CSharp/MeasurementModel.cs
@@ -46,7 +46,7 @@ public static MeasurementModel Create(MTConnectMeasurementModel importModel)
public string RenderModel()
{
- var template = TemplateLoader.LoadOrThrow("CSharp", "Templates", "Assets.Measurement.scriban");
+ var template = TemplateLoader.LoadOrThrow("CSharp", "Templates", "Pallets.Measurement.scriban");
return template.Render(this);
}
diff --git a/build/MTConnect.NET-SysML-Import/CSharp/TemplateRenderer.cs b/build/MTConnect.NET-SysML-Import/CSharp/TemplateRenderer.cs
index 6345c9a94..48e462cfc 100644
--- a/build/MTConnect.NET-SysML-Import/CSharp/TemplateRenderer.cs
+++ b/build/MTConnect.NET-SysML-Import/CSharp/TemplateRenderer.cs
@@ -92,7 +92,14 @@ public static void Render(MTConnectModel mtconnectModel, string outputPath)
else if (typeof(MTConnectCompositionType).IsAssignableFrom(type)) template = CompositionType.Create((MTConnectCompositionType)exportModel);
else if (typeof(MTConnectComponentType).IsAssignableFrom(type))
{
- if (((MTConnectComponentType)exportModel).Type == "Controllers") ((MTConnectComponentType)exportModel).MinimumVersion = new Version(1, 0);
+ // Surface the SysML-declared introduction year
+ // for every Component, including the Controllers
+ // organizer AssociationClass (introduced='2.0').
+ // The earlier override that hard-coded Controllers
+ // to v1.0 contradicted the spec — the
+ // `Profile:normative introduced='2.0'` record
+ // on the Controllers UML AssociationClass is the
+ // authoritative source.
template = ComponentType.Create((MTConnectComponentType)exportModel);
}
else if (typeof(MTConnectMeasurementModel).IsAssignableFrom(type))
@@ -101,15 +108,15 @@ public static void Render(MTConnectModel mtconnectModel, string outputPath)
{
template = CuttingToolMeasurementModel.Create((MTConnectMeasurementModel)exportModel);
}
- else
+ else if (exportModel.Id?.StartsWith("Assets.Pallet.") == true)
{
- // Non-CuttingTools measurement (e.g. Assets.Pallet.*) — no fallback
- // template exists yet, so log and continue rather than silently
- // dropping the model.
- Console.Error.WriteLine(
- $"warn: MeasurementModel '{exportModel.Id}' has no template — " +
- "only Assets.CuttingTools.* is currently rendered. Skipping.");
+ template = MeasurementModel.Create((MTConnectMeasurementModel)exportModel);
}
+ // No fallback: every measurement in the v2.x SysML routes
+ // through one of the two prefixes above. A future model
+ // adding a third measurement package will surface here as a
+ // null template (NullReferenceException downstream) — preferable
+ // to a silent drop with a stderr warning that nothing watches.
}
else if (typeof(MTConnectClassModel).IsAssignableFrom(type) && exportModel.Id?.EndsWith("Result") == true)
{
@@ -193,6 +200,16 @@ public static void Render(MTConnectModel mtconnectModel, string outputPath)
((ClassModel)template).IsPartial = true;
((ClassModel)template).IsAbstract = false;
break;
+ case "Assets.Pallet.Measurement":
+ // Partial + concrete so a hand-written
+ // partial can supply the `Type` property
+ // and the `Measurement(IMeasurement)` ctor
+ // that the per-subtype rich template
+ // (`Pallets.Measurement.scriban`) chains
+ // to via `: base(measurement)`.
+ ((ClassModel)template).IsPartial = true;
+ ((ClassModel)template).IsAbstract = false;
+ break;
}
templates.Add(template);
diff --git a/build/MTConnect.NET-SysML-Import/CSharp/Templates/Interfaces.InterfaceDataItemType.scriban b/build/MTConnect.NET-SysML-Import/CSharp/Templates/Interfaces.InterfaceDataItemType.scriban
index acc4d4648..475688a72 100644
--- a/build/MTConnect.NET-SysML-Import/CSharp/Templates/Interfaces.InterfaceDataItemType.scriban
+++ b/build/MTConnect.NET-SysML-Import/CSharp/Templates/Interfaces.InterfaceDataItemType.scriban
@@ -13,14 +13,27 @@ namespace MTConnect.Interfaces
public const DataItemCategory CategoryId = DataItemCategory.{{category}};
public const string TypeId = "{{type}}";
public const string NameId = "{{default_name}}";
- {{ if (units_enum) }}public const string DefaultUnits = {{units_enum}};{{ end }}
+ {{ if (units_enum) }}public const string DefaultUnits = {{units_enum}};{{ end }}
public new const string DescriptionText = "{{description}}";
-
+
public override string TypeDescription => DescriptionText;
{{ if (maximum_version_enum) }}public override System.Version MaximumVersion => {{maximum_version_enum}};{{ end }}
- {{ if (minimum_version_enum) }}public override System.Version MinimumVersion => {{minimum_version_enum}};{{ end }}
+ {{ if (minimum_version_enum) }}public override System.Version MinimumVersion => {{minimum_version_enum}};{{ end }}
+{{ if ((sub_types | array.size) > 0) }}{{ i = 0 }}
+ public new enum SubTypes
+ {
+{{- for sub_type in sub_types }}{{ i = i + 1 }}
+ ///
+ /// {{sub_type.description}}
+ ///
+ {{sub_type.name}}
+ {{- if (i < (sub_types | array.size)) }},
+ {{ end }}
+{{- end }}
+ }
+{{ end }}
public {{name}}()
{
Category = CategoryId;
@@ -28,6 +41,54 @@ namespace MTConnect.Interfaces
{{ if (units_enum) }}Units = DefaultUnits;{{ end }}
}
+{{- if ((sub_types | array.size) > 0) }}
+
+ public {{name}}(
+ string parentId,
+ SubTypes subType
+ )
+ {
+ Id = CreateId(parentId, NameId, GetSubTypeId(subType));
+ Category = CategoryId;
+ Type = TypeId;
+ SubType = subType.ToString();
+ Name = NameId;
+ {{ if (units_enum) }}Units = DefaultUnits;{{ end }}
+ }
+
+ public override string SubTypeDescription => GetSubTypeDescription(SubType);
+
+{{- if ((sub_types | array.size) > 0) }}{{ i = 0 }}
+
+ public new static string GetSubTypeDescription(string subType)
+ {
+ var s = subType.ConvertEnum();
+ switch (s)
+ {
+{{- for sub_type in sub_types }}{{ i = i + 1 }}
+ case SubTypes.{{sub_type.name}}: return "{{sub_type.description}}";
+{{- end }}
+ }
+
+ return null;
+ }
+{{- end }}
+{{- if ((sub_types | array.size) > 0) }}{{ i = 0 }}
+
+ public new static string GetSubTypeId(SubTypes subType)
+ {
+ switch (subType)
+ {
+{{- for sub_type in sub_types }}{{ i = i + 1 }}
+ case SubTypes.{{sub_type.name}}: return "{{sub_type.name}}";
+{{- end }}
+ }
+
+ return null;
+ }
+{{- end }}
+{{ else }}
+
public {{name}}(string deviceId)
{
Id = CreateId(deviceId, NameId);
@@ -35,5 +96,6 @@ namespace MTConnect.Interfaces
Type = TypeId;
Name = NameId;
}
+{{- end }}
}
-}
\ No newline at end of file
+}
diff --git a/build/MTConnect.NET-SysML-Import/CSharp/Templates/Pallets.Measurement.scriban b/build/MTConnect.NET-SysML-Import/CSharp/Templates/Pallets.Measurement.scriban
index 5cba268cf..c92505e04 100644
--- a/build/MTConnect.NET-SysML-Import/CSharp/Templates/Pallets.Measurement.scriban
+++ b/build/MTConnect.NET-SysML-Import/CSharp/Templates/Pallets.Measurement.scriban
@@ -1,12 +1,12 @@
// Copyright (c) 2025 TrakHound Inc., All Rights Reserved.
// TrakHound Inc. licenses this file to you under the MIT license.
-namespace MTConnect.Assets.Pallet.Measurements
+namespace {{namespace}}
{
///
/// {{description}}
///
- public class {{name}} : Measurement
+ public class {{name}} : Measurement, I{{name}}
{
public const string TypeId = "{{type_id}}";
public const string CodeId = "{{code_id}}";
@@ -15,14 +15,12 @@ namespace MTConnect.Assets.Pallet.Measurements
public {{name}}()
{
Type = TypeId;
- Code = CodeId;
{{ if (units_enum) }}Units = {{units_enum}};{{ end }}
}
public {{name}}(double value)
{
Type = TypeId;
- Code = CodeId;
Value = value;
{{ if (units_enum) }}Units = {{units_enum}};{{ end }}
}
@@ -30,7 +28,6 @@ namespace MTConnect.Assets.Pallet.Measurements
public {{name}}(IMeasurement measurement) : base(measurement)
{
Type = TypeId;
- Code = CodeId;
{{ if (units_enum) }}Units = {{units_enum}};{{ end }}
}
}
diff --git a/libraries/MTConnect.NET-Common/Agents/MTConnectAgent.cs b/libraries/MTConnect.NET-Common/Agents/MTConnectAgent.cs
index 7e455f4c6..c928ceee5 100644
--- a/libraries/MTConnect.NET-Common/Agents/MTConnectAgent.cs
+++ b/libraries/MTConnect.NET-Common/Agents/MTConnectAgent.cs
@@ -1171,11 +1171,6 @@ private Device NormalizeDevice(IDevice device)
assetcount.Device = obj;
assetcount.Container = obj;
assetcount.Name = AssetCountDataItem.NameId;
- // ASSET_COUNT is a DATA_SET representation per MTConnect Part 2
- // (UML _19_0_3_68e0225_1640602520420_217627_44). The generated
- // AssetCountDataItem still defaults Representation to VALUE; override
- // it here so the auto-injected DataItem matches the spec.
- assetcount.Representation = DataItemRepresentation.DATA_SET;
dataItemList.Add(assetcount);
dataItemTypes.Add(AssetCountDataItem.TypeId);
}
diff --git a/libraries/MTConnect.NET-Common/Assets/Pallet/HeightMeasurement.g.cs b/libraries/MTConnect.NET-Common/Assets/Pallet/HeightMeasurement.g.cs
index c95fd01eb..5370fef58 100644
--- a/libraries/MTConnect.NET-Common/Assets/Pallet/HeightMeasurement.g.cs
+++ b/libraries/MTConnect.NET-Common/Assets/Pallet/HeightMeasurement.g.cs
@@ -1,8 +1,6 @@
-// Copyright (c) 2024 TrakHound Inc., All Rights Reserved.
+// Copyright (c) 2025 TrakHound Inc., All Rights Reserved.
// TrakHound Inc. licenses this file to you under the MIT license.
-// MTConnect SysML v2.3 : UML ID = _2024x_68e0225_1727795946018_306044_24580
-
namespace MTConnect.Assets.Pallet
{
///
@@ -11,7 +9,27 @@ namespace MTConnect.Assets.Pallet
public class HeightMeasurement : Measurement, IHeightMeasurement
{
public new const string DescriptionText = "Height of the PhysicalAsset";
+ public const string TypeId = "Height";
+ public const string CodeId = "";
+
+
+ public HeightMeasurement()
+ {
+ Type = TypeId;
+
+ }
+ public HeightMeasurement(double value)
+ {
+ Type = TypeId;
+ Value = value;
+
+ }
+ public HeightMeasurement(IMeasurement measurement) : base(measurement)
+ {
+ Type = TypeId;
+
+ }
}
}
\ No newline at end of file
diff --git a/libraries/MTConnect.NET-Common/Assets/Pallet/IMeasurement.g.cs b/libraries/MTConnect.NET-Common/Assets/Pallet/IMeasurement.g.cs
index e4a72758f..37b3be996 100644
--- a/libraries/MTConnect.NET-Common/Assets/Pallet/IMeasurement.g.cs
+++ b/libraries/MTConnect.NET-Common/Assets/Pallet/IMeasurement.g.cs
@@ -6,7 +6,7 @@ namespace MTConnect.Assets.Pallet
///
/// Constrained scalar value associated with an Asset
///
- public interface IMeasurement
+ public partial interface IMeasurement
{
///
/// Maximum value for the measurement.
diff --git a/libraries/MTConnect.NET-Common/Assets/Pallet/LengthMeasurement.g.cs b/libraries/MTConnect.NET-Common/Assets/Pallet/LengthMeasurement.g.cs
index 1533e5d98..92cac40b2 100644
--- a/libraries/MTConnect.NET-Common/Assets/Pallet/LengthMeasurement.g.cs
+++ b/libraries/MTConnect.NET-Common/Assets/Pallet/LengthMeasurement.g.cs
@@ -1,8 +1,6 @@
-// Copyright (c) 2024 TrakHound Inc., All Rights Reserved.
+// Copyright (c) 2025 TrakHound Inc., All Rights Reserved.
// TrakHound Inc. licenses this file to you under the MIT license.
-// MTConnect SysML v2.3 : UML ID = _2024x_68e0225_1727795955654_438848_24650
-
namespace MTConnect.Assets.Pallet
{
///
@@ -11,7 +9,27 @@ namespace MTConnect.Assets.Pallet
public class LengthMeasurement : Measurement, ILengthMeasurement
{
public new const string DescriptionText = "Length of the PhysicalAsset";
+ public const string TypeId = "Length";
+ public const string CodeId = "";
+
+
+ public LengthMeasurement()
+ {
+ Type = TypeId;
+
+ }
+ public LengthMeasurement(double value)
+ {
+ Type = TypeId;
+ Value = value;
+
+ }
+ public LengthMeasurement(IMeasurement measurement) : base(measurement)
+ {
+ Type = TypeId;
+
+ }
}
}
\ No newline at end of file
diff --git a/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedHeightMeasurement.g.cs b/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedHeightMeasurement.g.cs
index 36881c6d8..68ca5111b 100644
--- a/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedHeightMeasurement.g.cs
+++ b/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedHeightMeasurement.g.cs
@@ -1,8 +1,6 @@
-// Copyright (c) 2024 TrakHound Inc., All Rights Reserved.
+// Copyright (c) 2025 TrakHound Inc., All Rights Reserved.
// TrakHound Inc. licenses this file to you under the MIT license.
-// MTConnect SysML v2.3 : UML ID = _2024x_68e0225_1727795985316_21813_24755
-
namespace MTConnect.Assets.Pallet
{
///
@@ -11,7 +9,27 @@ namespace MTConnect.Assets.Pallet
public class LoadedHeightMeasurement : Measurement, ILoadedHeightMeasurement
{
public new const string DescriptionText = "Loaded height of the PhysicalAsset";
+ public const string TypeId = "LoadedHeight";
+ public const string CodeId = "";
+
+
+ public LoadedHeightMeasurement()
+ {
+ Type = TypeId;
+
+ }
+ public LoadedHeightMeasurement(double value)
+ {
+ Type = TypeId;
+ Value = value;
+
+ }
+ public LoadedHeightMeasurement(IMeasurement measurement) : base(measurement)
+ {
+ Type = TypeId;
+
+ }
}
}
\ No newline at end of file
diff --git a/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedLengthMeasurement.g.cs b/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedLengthMeasurement.g.cs
index 707ced57d..5aff580bf 100644
--- a/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedLengthMeasurement.g.cs
+++ b/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedLengthMeasurement.g.cs
@@ -1,8 +1,6 @@
-// Copyright (c) 2024 TrakHound Inc., All Rights Reserved.
+// Copyright (c) 2025 TrakHound Inc., All Rights Reserved.
// TrakHound Inc. licenses this file to you under the MIT license.
-// MTConnect SysML v2.3 : UML ID = _2024x_68e0225_1727796000098_310953_24825
-
namespace MTConnect.Assets.Pallet
{
///
@@ -11,7 +9,27 @@ namespace MTConnect.Assets.Pallet
public class LoadedLengthMeasurement : Measurement, ILoadedLengthMeasurement
{
public new const string DescriptionText = "Loaded length of the PhysicalAsset";
+ public const string TypeId = "LoadedLength";
+ public const string CodeId = "";
+
+
+ public LoadedLengthMeasurement()
+ {
+ Type = TypeId;
+
+ }
+ public LoadedLengthMeasurement(double value)
+ {
+ Type = TypeId;
+ Value = value;
+
+ }
+ public LoadedLengthMeasurement(IMeasurement measurement) : base(measurement)
+ {
+ Type = TypeId;
+
+ }
}
}
\ No newline at end of file
diff --git a/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedSwingMeasurement.g.cs b/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedSwingMeasurement.g.cs
index c8a18638e..c270fb137 100644
--- a/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedSwingMeasurement.g.cs
+++ b/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedSwingMeasurement.g.cs
@@ -1,8 +1,6 @@
-// Copyright (c) 2024 TrakHound Inc., All Rights Reserved.
+// Copyright (c) 2025 TrakHound Inc., All Rights Reserved.
// TrakHound Inc. licenses this file to you under the MIT license.
-// MTConnect SysML v2.3 : UML ID = _2024x_68e0225_1727796007725_733990_24860
-
namespace MTConnect.Assets.Pallet
{
///
@@ -11,7 +9,27 @@ namespace MTConnect.Assets.Pallet
public class LoadedSwingMeasurement : Measurement, ILoadedSwingMeasurement
{
public new const string DescriptionText = "Loaded swing of the PhysicalAsset";
+ public const string TypeId = "LoadedSwing";
+ public const string CodeId = "";
+
+
+ public LoadedSwingMeasurement()
+ {
+ Type = TypeId;
+
+ }
+ public LoadedSwingMeasurement(double value)
+ {
+ Type = TypeId;
+ Value = value;
+
+ }
+ public LoadedSwingMeasurement(IMeasurement measurement) : base(measurement)
+ {
+ Type = TypeId;
+
+ }
}
}
\ No newline at end of file
diff --git a/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedWeightMeasurement.g.cs b/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedWeightMeasurement.g.cs
index 497ac2482..db15ecc9e 100644
--- a/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedWeightMeasurement.g.cs
+++ b/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedWeightMeasurement.g.cs
@@ -1,8 +1,6 @@
-// Copyright (c) 2024 TrakHound Inc., All Rights Reserved.
+// Copyright (c) 2025 TrakHound Inc., All Rights Reserved.
// TrakHound Inc. licenses this file to you under the MIT license.
-// MTConnect SysML v2.3 : UML ID = _2024x_68e0225_1727795966065_979190_24720
-
namespace MTConnect.Assets.Pallet
{
///
@@ -11,7 +9,27 @@ namespace MTConnect.Assets.Pallet
public class LoadedWeightMeasurement : Measurement, ILoadedWeightMeasurement
{
public new const string DescriptionText = "Loaded weight of the PhysicalAsset";
+ public const string TypeId = "LoadedWeight";
+ public const string CodeId = "";
+
+
+ public LoadedWeightMeasurement()
+ {
+ Type = TypeId;
+
+ }
+ public LoadedWeightMeasurement(double value)
+ {
+ Type = TypeId;
+ Value = value;
+
+ }
+ public LoadedWeightMeasurement(IMeasurement measurement) : base(measurement)
+ {
+ Type = TypeId;
+
+ }
}
}
\ No newline at end of file
diff --git a/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedWidthMeasurement.g.cs b/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedWidthMeasurement.g.cs
index 1b0c3ab78..c82b3f08e 100644
--- a/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedWidthMeasurement.g.cs
+++ b/libraries/MTConnect.NET-Common/Assets/Pallet/LoadedWidthMeasurement.g.cs
@@ -1,8 +1,6 @@
-// Copyright (c) 2024 TrakHound Inc., All Rights Reserved.
+// Copyright (c) 2025 TrakHound Inc., All Rights Reserved.
// TrakHound Inc. licenses this file to you under the MIT license.
-// MTConnect SysML v2.3 : UML ID = _2024x_68e0225_1727795992160_973071_24790
-
namespace MTConnect.Assets.Pallet
{
///
@@ -11,7 +9,27 @@ namespace MTConnect.Assets.Pallet
public class LoadedWidthMeasurement : Measurement, ILoadedWidthMeasurement
{
public new const string DescriptionText = "Loaded width of the PhysicalAsset";
+ public const string TypeId = "LoadedWidth";
+ public const string CodeId = "";
+
+
+ public LoadedWidthMeasurement()
+ {
+ Type = TypeId;
+
+ }
+ public LoadedWidthMeasurement(double value)
+ {
+ Type = TypeId;
+ Value = value;
+
+ }
+ public LoadedWidthMeasurement(IMeasurement measurement) : base(measurement)
+ {
+ Type = TypeId;
+
+ }
}
}
\ No newline at end of file
diff --git a/libraries/MTConnect.NET-Common/Assets/Pallet/Measurement.cs b/libraries/MTConnect.NET-Common/Assets/Pallet/Measurement.cs
new file mode 100644
index 000000000..c1d8e71c9
--- /dev/null
+++ b/libraries/MTConnect.NET-Common/Assets/Pallet/Measurement.cs
@@ -0,0 +1,27 @@
+// Copyright (c) 2025 TrakHound Inc., All Rights Reserved.
+// TrakHound Inc. licenses this file to you under the MIT license.
+
+namespace MTConnect.Assets.Pallet
+{
+ public partial class Measurement
+ {
+ public string Type { get; set; }
+
+
+ public Measurement() { }
+
+ public Measurement(IMeasurement measurement)
+ {
+ if (measurement != null)
+ {
+ Value = measurement.Value;
+ Nominal = measurement.Nominal;
+ Minimum = measurement.Minimum;
+ Maximum = measurement.Maximum;
+ SignificantDigits = measurement.SignificantDigits;
+ NativeUnits = measurement.NativeUnits;
+ Units = measurement.Units;
+ }
+ }
+ }
+}
diff --git a/libraries/MTConnect.NET-Common/Assets/Pallet/Measurement.g.cs b/libraries/MTConnect.NET-Common/Assets/Pallet/Measurement.g.cs
index d8f146c42..2b8f5ee24 100644
--- a/libraries/MTConnect.NET-Common/Assets/Pallet/Measurement.g.cs
+++ b/libraries/MTConnect.NET-Common/Assets/Pallet/Measurement.g.cs
@@ -8,7 +8,7 @@ namespace MTConnect.Assets.Pallet
///
/// Constrained scalar value associated with an Asset
///
- public abstract class Measurement : IMeasurement
+ public partial class Measurement : IMeasurement
{
public const string DescriptionText = "Constrained scalar value associated with an Asset";
diff --git a/libraries/MTConnect.NET-Common/Assets/Pallet/SwingMeasurement.g.cs b/libraries/MTConnect.NET-Common/Assets/Pallet/SwingMeasurement.g.cs
index dcee10d6c..3c7fc0f64 100644
--- a/libraries/MTConnect.NET-Common/Assets/Pallet/SwingMeasurement.g.cs
+++ b/libraries/MTConnect.NET-Common/Assets/Pallet/SwingMeasurement.g.cs
@@ -1,8 +1,6 @@
-// Copyright (c) 2024 TrakHound Inc., All Rights Reserved.
+// Copyright (c) 2025 TrakHound Inc., All Rights Reserved.
// TrakHound Inc. licenses this file to you under the MIT license.
-// MTConnect SysML v2.3 : UML ID = _2024x_68e0225_1727795961263_1895_24685
-
namespace MTConnect.Assets.Pallet
{
///
@@ -11,7 +9,27 @@ namespace MTConnect.Assets.Pallet
public class SwingMeasurement : Measurement, ISwingMeasurement
{
public new const string DescriptionText = "Swing of the PhysicalAsset";
+ public const string TypeId = "Swing";
+ public const string CodeId = "";
+
+
+ public SwingMeasurement()
+ {
+ Type = TypeId;
+
+ }
+ public SwingMeasurement(double value)
+ {
+ Type = TypeId;
+ Value = value;
+
+ }
+ public SwingMeasurement(IMeasurement measurement) : base(measurement)
+ {
+ Type = TypeId;
+
+ }
}
}
\ No newline at end of file
diff --git a/libraries/MTConnect.NET-Common/Assets/Pallet/WeightMeasurement.g.cs b/libraries/MTConnect.NET-Common/Assets/Pallet/WeightMeasurement.g.cs
index 80f3c8356..06b8b0954 100644
--- a/libraries/MTConnect.NET-Common/Assets/Pallet/WeightMeasurement.g.cs
+++ b/libraries/MTConnect.NET-Common/Assets/Pallet/WeightMeasurement.g.cs
@@ -1,8 +1,6 @@
-// Copyright (c) 2024 TrakHound Inc., All Rights Reserved.
+// Copyright (c) 2025 TrakHound Inc., All Rights Reserved.
// TrakHound Inc. licenses this file to you under the MIT license.
-// MTConnect SysML v2.3 : UML ID = _2024x_68e0225_1727795939487_321518_24545
-
namespace MTConnect.Assets.Pallet
{
///
@@ -11,7 +9,27 @@ namespace MTConnect.Assets.Pallet
public class WeightMeasurement : Measurement, IWeightMeasurement
{
public new const string DescriptionText = "Weight of the PhysicalAsset";
+ public const string TypeId = "Weight";
+ public const string CodeId = "";
+
+
+ public WeightMeasurement()
+ {
+ Type = TypeId;
+
+ }
+ public WeightMeasurement(double value)
+ {
+ Type = TypeId;
+ Value = value;
+
+ }
+ public WeightMeasurement(IMeasurement measurement) : base(measurement)
+ {
+ Type = TypeId;
+
+ }
}
}
\ No newline at end of file
diff --git a/libraries/MTConnect.NET-Common/Assets/Pallet/WidthMeasurement.g.cs b/libraries/MTConnect.NET-Common/Assets/Pallet/WidthMeasurement.g.cs
index 580aa1d27..e00685d10 100644
--- a/libraries/MTConnect.NET-Common/Assets/Pallet/WidthMeasurement.g.cs
+++ b/libraries/MTConnect.NET-Common/Assets/Pallet/WidthMeasurement.g.cs
@@ -1,8 +1,6 @@
-// Copyright (c) 2024 TrakHound Inc., All Rights Reserved.
+// Copyright (c) 2025 TrakHound Inc., All Rights Reserved.
// TrakHound Inc. licenses this file to you under the MIT license.
-// MTConnect SysML v2.3 : UML ID = _2024x_68e0225_1727795950849_939647_24615
-
namespace MTConnect.Assets.Pallet
{
///
@@ -11,7 +9,27 @@ namespace MTConnect.Assets.Pallet
public class WidthMeasurement : Measurement, IWidthMeasurement
{
public new const string DescriptionText = "Width of the PhysicalAsset";
+ public const string TypeId = "Width";
+ public const string CodeId = "";
+
+
+ public WidthMeasurement()
+ {
+ Type = TypeId;
+
+ }
+ public WidthMeasurement(double value)
+ {
+ Type = TypeId;
+ Value = value;
+
+ }
+ public WidthMeasurement(IMeasurement measurement) : base(measurement)
+ {
+ Type = TypeId;
+
+ }
}
}
\ No newline at end of file
diff --git a/libraries/MTConnect.NET-Common/Devices/Components/ControllersComponent.g.cs b/libraries/MTConnect.NET-Common/Devices/Components/ControllersComponent.g.cs
index c0607d3c1..f9e00cb57 100644
--- a/libraries/MTConnect.NET-Common/Devices/Components/ControllersComponent.g.cs
+++ b/libraries/MTConnect.NET-Common/Devices/Components/ControllersComponent.g.cs
@@ -16,7 +16,7 @@ public class ControllersComponent : Component, IOrganizerComponent
public override string TypeDescription => DescriptionText;
- public override System.Version MinimumVersion => MTConnectVersions.Version10;
+ public override System.Version MinimumVersion => MTConnectVersions.Version20;
public ControllersComponent()
diff --git a/libraries/MTConnect.NET-Common/Devices/DataItems/AlarmLimitDataItem.g.cs b/libraries/MTConnect.NET-Common/Devices/DataItems/AlarmLimitDataItem.g.cs
index d5257779f..f2a7eba51 100644
--- a/libraries/MTConnect.NET-Common/Devices/DataItems/AlarmLimitDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Devices/DataItems/AlarmLimitDataItem.g.cs
@@ -13,7 +13,7 @@ public class AlarmLimitDataItem : DataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "ALARM_LIMIT";
public const string NameId = "alarmLimit";
- public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.TABLE;
+ public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.DATA_SET;
public new const string DescriptionText = "Set of limits used to trigger warning or alarm indicators.**DEPRECATED** in *Version 2.5*. Replaced by `ALARM_LIMITS`.";
diff --git a/libraries/MTConnect.NET-Common/Devices/DataItems/AlarmLimitsDataItem.g.cs b/libraries/MTConnect.NET-Common/Devices/DataItems/AlarmLimitsDataItem.g.cs
index b2c468028..24c189edd 100644
--- a/libraries/MTConnect.NET-Common/Devices/DataItems/AlarmLimitsDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Devices/DataItems/AlarmLimitsDataItem.g.cs
@@ -13,7 +13,7 @@ public class AlarmLimitsDataItem : DataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "ALARM_LIMITS";
public const string NameId = "alarmLimits";
- public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.TABLE;
+ public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.DATA_SET;
public new const string DescriptionText = "Set of limits used to trigger warning or alarm indicators.";
diff --git a/libraries/MTConnect.NET-Common/Devices/DataItems/AssetCountDataItem.g.cs b/libraries/MTConnect.NET-Common/Devices/DataItems/AssetCountDataItem.g.cs
index 44ba100df..bfa4fca6e 100644
--- a/libraries/MTConnect.NET-Common/Devices/DataItems/AssetCountDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Devices/DataItems/AssetCountDataItem.g.cs
@@ -13,7 +13,7 @@ public class AssetCountDataItem : DataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "ASSET_COUNT";
public const string NameId = "assetCount";
- public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.VALUE;
+ public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.DATA_SET;
public new const string DescriptionText = "Data set of the number of Asset of a given type for a Device.";
diff --git a/libraries/MTConnect.NET-Common/Devices/DataItems/ControlLimitDataItem.g.cs b/libraries/MTConnect.NET-Common/Devices/DataItems/ControlLimitDataItem.g.cs
index 59e10706a..ae610f873 100644
--- a/libraries/MTConnect.NET-Common/Devices/DataItems/ControlLimitDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Devices/DataItems/ControlLimitDataItem.g.cs
@@ -13,7 +13,7 @@ public class ControlLimitDataItem : DataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "CONTROL_LIMIT";
public const string NameId = "controlLimit";
- public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.TABLE;
+ public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.DATA_SET;
public new const string DescriptionText = "Set of limits used to indicate whether a process variable is stable and in control.**DEPRECATED** in *Version 2.5*. Replaced by `CONTROL_LIMITS`.";
diff --git a/libraries/MTConnect.NET-Common/Devices/DataItems/ControlLimitsDataItem.g.cs b/libraries/MTConnect.NET-Common/Devices/DataItems/ControlLimitsDataItem.g.cs
index 3215018b8..c370c018c 100644
--- a/libraries/MTConnect.NET-Common/Devices/DataItems/ControlLimitsDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Devices/DataItems/ControlLimitsDataItem.g.cs
@@ -13,7 +13,7 @@ public class ControlLimitsDataItem : DataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "CONTROL_LIMITS";
public const string NameId = "controlLimits";
- public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.TABLE;
+ public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.DATA_SET;
public new const string DescriptionText = "Set of limits used to indicate whether a process variable is stable and in control.";
diff --git a/libraries/MTConnect.NET-Common/Devices/DataItems/LocationAddressDataItem.g.cs b/libraries/MTConnect.NET-Common/Devices/DataItems/LocationAddressDataItem.g.cs
index 3c164808a..a5a842c04 100644
--- a/libraries/MTConnect.NET-Common/Devices/DataItems/LocationAddressDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Devices/DataItems/LocationAddressDataItem.g.cs
@@ -13,7 +13,7 @@ public class LocationAddressDataItem : DataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "LOCATION_ADDRESS";
public const string NameId = "locationAddress";
- public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.TABLE;
+ public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.DATA_SET;
public new const string DescriptionText = "Structured information that allows the unambiguous determination of an object for purposes of identification and location. ISO 19160-4:2017";
diff --git a/libraries/MTConnect.NET-Common/Devices/DataItems/LocationSpatialGeographicDataItem.g.cs b/libraries/MTConnect.NET-Common/Devices/DataItems/LocationSpatialGeographicDataItem.g.cs
index 41d91493d..b5c81fc6e 100644
--- a/libraries/MTConnect.NET-Common/Devices/DataItems/LocationSpatialGeographicDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Devices/DataItems/LocationSpatialGeographicDataItem.g.cs
@@ -13,7 +13,7 @@ public class LocationSpatialGeographicDataItem : DataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "LOCATION_SPATIAL_GEOGRAPHIC";
public const string NameId = "locationSpatialGeographic";
- public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.TABLE;
+ public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.DATA_SET;
public new const string DescriptionText = "Absolute geographic location defined by two coordinates, longitude and latitude and an elevation.";
diff --git a/libraries/MTConnect.NET-Common/Devices/DataItems/SensorAttachmentDataItem.g.cs b/libraries/MTConnect.NET-Common/Devices/DataItems/SensorAttachmentDataItem.g.cs
index b7ed5e378..e55193931 100644
--- a/libraries/MTConnect.NET-Common/Devices/DataItems/SensorAttachmentDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Devices/DataItems/SensorAttachmentDataItem.g.cs
@@ -13,7 +13,7 @@ public class SensorAttachmentDataItem : DataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "SENSOR_ATTACHMENT";
public const string NameId = "sensorAttachment";
- public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.TABLE;
+ public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.DATA_SET;
public new const string DescriptionText = "Attachment between a sensor and an entity.";
diff --git a/libraries/MTConnect.NET-Common/Devices/DataItems/SpecificationLimitDataItem.g.cs b/libraries/MTConnect.NET-Common/Devices/DataItems/SpecificationLimitDataItem.g.cs
index 254d376d8..a588fc5bb 100644
--- a/libraries/MTConnect.NET-Common/Devices/DataItems/SpecificationLimitDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Devices/DataItems/SpecificationLimitDataItem.g.cs
@@ -13,7 +13,7 @@ public class SpecificationLimitDataItem : DataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "SPECIFICATION_LIMIT";
public const string NameId = "specificationLimit";
- public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.TABLE;
+ public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.DATA_SET;
public new const string DescriptionText = "Set of limits defining a range of values designating acceptable performance for a variable.**DEPRECATED** in *Version 2.5*. Replaced by `SPECIFICATION_LIMITS`.";
diff --git a/libraries/MTConnect.NET-Common/Devices/DataItems/SpecificationLimitsDataItem.g.cs b/libraries/MTConnect.NET-Common/Devices/DataItems/SpecificationLimitsDataItem.g.cs
index ef2e8c215..91d2286ac 100644
--- a/libraries/MTConnect.NET-Common/Devices/DataItems/SpecificationLimitsDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Devices/DataItems/SpecificationLimitsDataItem.g.cs
@@ -13,7 +13,7 @@ public class SpecificationLimitsDataItem : DataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "SPECIFICATION_LIMITS";
public const string NameId = "specificationLimits";
- public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.TABLE;
+ public const DataItemRepresentation DefaultRepresentation = DataItemRepresentation.DATA_SET;
public new const string DescriptionText = "Set of limits defining a range of values designating acceptable performance for a variable.";
diff --git a/libraries/MTConnect.NET-Common/Interfaces/CloseChuckDataItem.g.cs b/libraries/MTConnect.NET-Common/Interfaces/CloseChuckDataItem.g.cs
index 127c4c6a5..2d3d27329 100644
--- a/libraries/MTConnect.NET-Common/Interfaces/CloseChuckDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Interfaces/CloseChuckDataItem.g.cs
@@ -13,12 +13,26 @@ public class CloseChuckDataItem : InterfaceDataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "CLOSE_CHUCK";
public const string NameId = "closeChuck";
-
- public new const string DescriptionText = "Operating state of the service to close a chuck.";
+ public new const string DescriptionText = "Operating state of the service to close a chuck.";
+
public override string TypeDescription => DescriptionText;
- public override System.Version MinimumVersion => MTConnectVersions.Version13;
+ public override System.Version MinimumVersion => MTConnectVersions.Version13;
+
+
+ public new enum SubTypes
+ {
+ ///
+ /// Operating state of the request to close a chuck.
+ ///
+ REQUEST,
+
+ ///
+ /// Operating state of the response to a request to close a chuck.
+ ///
+ RESPONSE
+ }
public CloseChuckDataItem()
@@ -28,12 +42,43 @@ public CloseChuckDataItem()
}
- public CloseChuckDataItem(string deviceId)
+ public CloseChuckDataItem(
+ string parentId,
+ SubTypes subType
+ )
{
- Id = CreateId(deviceId, NameId);
+ Id = CreateId(parentId, NameId, GetSubTypeId(subType));
Category = CategoryId;
Type = TypeId;
+ SubType = subType.ToString();
Name = NameId;
+
}
+
+ public override string SubTypeDescription => GetSubTypeDescription(SubType);
+
+ public new static string GetSubTypeDescription(string subType)
+ {
+ var s = subType.ConvertEnum();
+ switch (s)
+ {
+ case SubTypes.REQUEST: return "Operating state of the request to close a chuck.";
+ case SubTypes.RESPONSE: return "Operating state of the response to a request to close a chuck.";
+ }
+
+ return null;
+ }
+
+ public new static string GetSubTypeId(SubTypes subType)
+ {
+ switch (subType)
+ {
+ case SubTypes.REQUEST: return "REQUEST";
+ case SubTypes.RESPONSE: return "RESPONSE";
+ }
+
+ return null;
+ }
+
}
-}
\ No newline at end of file
+}
diff --git a/libraries/MTConnect.NET-Common/Interfaces/CloseDoorDataItem.g.cs b/libraries/MTConnect.NET-Common/Interfaces/CloseDoorDataItem.g.cs
index 224dd1337..720bc6fd7 100644
--- a/libraries/MTConnect.NET-Common/Interfaces/CloseDoorDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Interfaces/CloseDoorDataItem.g.cs
@@ -13,12 +13,26 @@ public class CloseDoorDataItem : InterfaceDataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "CLOSE_DOOR";
public const string NameId = "closeDoor";
-
- public new const string DescriptionText = "Operating state of the service to close a door.";
+ public new const string DescriptionText = "Operating state of the service to close a door.";
+
public override string TypeDescription => DescriptionText;
- public override System.Version MinimumVersion => MTConnectVersions.Version13;
+ public override System.Version MinimumVersion => MTConnectVersions.Version13;
+
+
+ public new enum SubTypes
+ {
+ ///
+ /// Operating state of the request to close a door.
+ ///
+ REQUEST,
+
+ ///
+ /// Operating state of the response to a request to close a door.
+ ///
+ RESPONSE
+ }
public CloseDoorDataItem()
@@ -28,12 +42,43 @@ public CloseDoorDataItem()
}
- public CloseDoorDataItem(string deviceId)
+ public CloseDoorDataItem(
+ string parentId,
+ SubTypes subType
+ )
{
- Id = CreateId(deviceId, NameId);
+ Id = CreateId(parentId, NameId, GetSubTypeId(subType));
Category = CategoryId;
Type = TypeId;
+ SubType = subType.ToString();
Name = NameId;
+
}
+
+ public override string SubTypeDescription => GetSubTypeDescription(SubType);
+
+ public new static string GetSubTypeDescription(string subType)
+ {
+ var s = subType.ConvertEnum();
+ switch (s)
+ {
+ case SubTypes.REQUEST: return "Operating state of the request to close a door.";
+ case SubTypes.RESPONSE: return "Operating state of the response to a request to close a door.";
+ }
+
+ return null;
+ }
+
+ public new static string GetSubTypeId(SubTypes subType)
+ {
+ switch (subType)
+ {
+ case SubTypes.REQUEST: return "REQUEST";
+ case SubTypes.RESPONSE: return "RESPONSE";
+ }
+
+ return null;
+ }
+
}
-}
\ No newline at end of file
+}
diff --git a/libraries/MTConnect.NET-Common/Interfaces/MaterialChangeDataItem.g.cs b/libraries/MTConnect.NET-Common/Interfaces/MaterialChangeDataItem.g.cs
index 1637aca70..7d44a00aa 100644
--- a/libraries/MTConnect.NET-Common/Interfaces/MaterialChangeDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Interfaces/MaterialChangeDataItem.g.cs
@@ -13,12 +13,26 @@ public class MaterialChangeDataItem : InterfaceDataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "MATERIAL_CHANGE";
public const string NameId = "materialChange";
-
- public new const string DescriptionText = "Operating state of the service to change the type of material or product being loaded or fed to a piece of equipment.";
+ public new const string DescriptionText = "Operating state of the service to change the type of material or product being loaded or fed to a piece of equipment.";
+
public override string TypeDescription => DescriptionText;
- public override System.Version MinimumVersion => MTConnectVersions.Version13;
+ public override System.Version MinimumVersion => MTConnectVersions.Version13;
+
+
+ public new enum SubTypes
+ {
+ ///
+ /// Operating state of the request to change the type of material or product being loaded or fed to a piece of equipment.
+ ///
+ REQUEST,
+
+ ///
+ /// Operating state of the response to a request to change the type of material or product being loaded or fed to a piece of equipment.
+ ///
+ RESPONSE
+ }
public MaterialChangeDataItem()
@@ -28,12 +42,43 @@ public MaterialChangeDataItem()
}
- public MaterialChangeDataItem(string deviceId)
+ public MaterialChangeDataItem(
+ string parentId,
+ SubTypes subType
+ )
{
- Id = CreateId(deviceId, NameId);
+ Id = CreateId(parentId, NameId, GetSubTypeId(subType));
Category = CategoryId;
Type = TypeId;
+ SubType = subType.ToString();
Name = NameId;
+
}
+
+ public override string SubTypeDescription => GetSubTypeDescription(SubType);
+
+ public new static string GetSubTypeDescription(string subType)
+ {
+ var s = subType.ConvertEnum();
+ switch (s)
+ {
+ case SubTypes.REQUEST: return "Operating state of the request to change the type of material or product being loaded or fed to a piece of equipment.";
+ case SubTypes.RESPONSE: return "Operating state of the response to a request to change the type of material or product being loaded or fed to a piece of equipment.";
+ }
+
+ return null;
+ }
+
+ public new static string GetSubTypeId(SubTypes subType)
+ {
+ switch (subType)
+ {
+ case SubTypes.REQUEST: return "REQUEST";
+ case SubTypes.RESPONSE: return "RESPONSE";
+ }
+
+ return null;
+ }
+
}
-}
\ No newline at end of file
+}
diff --git a/libraries/MTConnect.NET-Common/Interfaces/MaterialFeedDataItem.g.cs b/libraries/MTConnect.NET-Common/Interfaces/MaterialFeedDataItem.g.cs
index cbc54c42c..82808028b 100644
--- a/libraries/MTConnect.NET-Common/Interfaces/MaterialFeedDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Interfaces/MaterialFeedDataItem.g.cs
@@ -13,12 +13,26 @@ public class MaterialFeedDataItem : InterfaceDataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "MATERIAL_FEED";
public const string NameId = "materialFeed";
-
- public new const string DescriptionText = "Operating state of the service to advance material or feed product to a piece of equipment from a continuous or bulk source.";
+ public new const string DescriptionText = "Operating state of the service to advance material or feed product to a piece of equipment from a continuous or bulk source.";
+
public override string TypeDescription => DescriptionText;
- public override System.Version MinimumVersion => MTConnectVersions.Version13;
+ public override System.Version MinimumVersion => MTConnectVersions.Version13;
+
+
+ public new enum SubTypes
+ {
+ ///
+ /// Operating state of the request to advance material or feed product to a piece of equipment from a continuous or bulk source.
+ ///
+ REQUEST,
+
+ ///
+ /// Operating state of the response to a request to advance material or feed product to a piece of equipment from a continuous or bulk source.
+ ///
+ RESPONSE
+ }
public MaterialFeedDataItem()
@@ -28,12 +42,43 @@ public MaterialFeedDataItem()
}
- public MaterialFeedDataItem(string deviceId)
+ public MaterialFeedDataItem(
+ string parentId,
+ SubTypes subType
+ )
{
- Id = CreateId(deviceId, NameId);
+ Id = CreateId(parentId, NameId, GetSubTypeId(subType));
Category = CategoryId;
Type = TypeId;
+ SubType = subType.ToString();
Name = NameId;
+
}
+
+ public override string SubTypeDescription => GetSubTypeDescription(SubType);
+
+ public new static string GetSubTypeDescription(string subType)
+ {
+ var s = subType.ConvertEnum();
+ switch (s)
+ {
+ case SubTypes.REQUEST: return "Operating state of the request to advance material or feed product to a piece of equipment from a continuous or bulk source.";
+ case SubTypes.RESPONSE: return "Operating state of the response to a request to advance material or feed product to a piece of equipment from a continuous or bulk source.";
+ }
+
+ return null;
+ }
+
+ public new static string GetSubTypeId(SubTypes subType)
+ {
+ switch (subType)
+ {
+ case SubTypes.REQUEST: return "REQUEST";
+ case SubTypes.RESPONSE: return "RESPONSE";
+ }
+
+ return null;
+ }
+
}
-}
\ No newline at end of file
+}
diff --git a/libraries/MTConnect.NET-Common/Interfaces/MaterialLoadDataItem.g.cs b/libraries/MTConnect.NET-Common/Interfaces/MaterialLoadDataItem.g.cs
index 640244915..0603498b1 100644
--- a/libraries/MTConnect.NET-Common/Interfaces/MaterialLoadDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Interfaces/MaterialLoadDataItem.g.cs
@@ -13,12 +13,26 @@ public class MaterialLoadDataItem : InterfaceDataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "MATERIAL_LOAD";
public const string NameId = "materialLoad";
-
- public new const string DescriptionText = "Operating state of the service to load a piece of material or product.";
+ public new const string DescriptionText = "Operating state of the service to load a piece of material or product.";
+
public override string TypeDescription => DescriptionText;
- public override System.Version MinimumVersion => MTConnectVersions.Version13;
+ public override System.Version MinimumVersion => MTConnectVersions.Version13;
+
+
+ public new enum SubTypes
+ {
+ ///
+ /// Operating state of the request to load a piece of material or product.
+ ///
+ REQUEST,
+
+ ///
+ /// Operating state of the response to a request to load a piece of material or product.
+ ///
+ RESPONSE
+ }
public MaterialLoadDataItem()
@@ -28,12 +42,43 @@ public MaterialLoadDataItem()
}
- public MaterialLoadDataItem(string deviceId)
+ public MaterialLoadDataItem(
+ string parentId,
+ SubTypes subType
+ )
{
- Id = CreateId(deviceId, NameId);
+ Id = CreateId(parentId, NameId, GetSubTypeId(subType));
Category = CategoryId;
Type = TypeId;
+ SubType = subType.ToString();
Name = NameId;
+
}
+
+ public override string SubTypeDescription => GetSubTypeDescription(SubType);
+
+ public new static string GetSubTypeDescription(string subType)
+ {
+ var s = subType.ConvertEnum();
+ switch (s)
+ {
+ case SubTypes.REQUEST: return "Operating state of the request to load a piece of material or product.";
+ case SubTypes.RESPONSE: return "Operating state of the response to a request to load a piece of material or product.";
+ }
+
+ return null;
+ }
+
+ public new static string GetSubTypeId(SubTypes subType)
+ {
+ switch (subType)
+ {
+ case SubTypes.REQUEST: return "REQUEST";
+ case SubTypes.RESPONSE: return "RESPONSE";
+ }
+
+ return null;
+ }
+
}
-}
\ No newline at end of file
+}
diff --git a/libraries/MTConnect.NET-Common/Interfaces/MaterialRetractDataItem.g.cs b/libraries/MTConnect.NET-Common/Interfaces/MaterialRetractDataItem.g.cs
index 0ba275bd6..fc3f5699d 100644
--- a/libraries/MTConnect.NET-Common/Interfaces/MaterialRetractDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Interfaces/MaterialRetractDataItem.g.cs
@@ -13,12 +13,26 @@ public class MaterialRetractDataItem : InterfaceDataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "MATERIAL_RETRACT";
public const string NameId = "materialRetract";
-
- public new const string DescriptionText = "Operating state of the service to remove or retract material or product.";
+ public new const string DescriptionText = "Operating state of the service to remove or retract material or product.";
+
public override string TypeDescription => DescriptionText;
- public override System.Version MinimumVersion => MTConnectVersions.Version13;
+ public override System.Version MinimumVersion => MTConnectVersions.Version13;
+
+
+ public new enum SubTypes
+ {
+ ///
+ /// Operating state of the request to remove or retract material or product.
+ ///
+ REQUEST,
+
+ ///
+ /// Operating state of the response to a request to remove or retract material or product.
+ ///
+ RESPONSE
+ }
public MaterialRetractDataItem()
@@ -28,12 +42,43 @@ public MaterialRetractDataItem()
}
- public MaterialRetractDataItem(string deviceId)
+ public MaterialRetractDataItem(
+ string parentId,
+ SubTypes subType
+ )
{
- Id = CreateId(deviceId, NameId);
+ Id = CreateId(parentId, NameId, GetSubTypeId(subType));
Category = CategoryId;
Type = TypeId;
+ SubType = subType.ToString();
Name = NameId;
+
}
+
+ public override string SubTypeDescription => GetSubTypeDescription(SubType);
+
+ public new static string GetSubTypeDescription(string subType)
+ {
+ var s = subType.ConvertEnum();
+ switch (s)
+ {
+ case SubTypes.REQUEST: return "Operating state of the request to remove or retract material or product.";
+ case SubTypes.RESPONSE: return "Operating state of the response to a request to remove or retract material or product.";
+ }
+
+ return null;
+ }
+
+ public new static string GetSubTypeId(SubTypes subType)
+ {
+ switch (subType)
+ {
+ case SubTypes.REQUEST: return "REQUEST";
+ case SubTypes.RESPONSE: return "RESPONSE";
+ }
+
+ return null;
+ }
+
}
-}
\ No newline at end of file
+}
diff --git a/libraries/MTConnect.NET-Common/Interfaces/MaterialUnloadDataItem.g.cs b/libraries/MTConnect.NET-Common/Interfaces/MaterialUnloadDataItem.g.cs
index 1d667f9f7..69e0b9367 100644
--- a/libraries/MTConnect.NET-Common/Interfaces/MaterialUnloadDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Interfaces/MaterialUnloadDataItem.g.cs
@@ -13,12 +13,26 @@ public class MaterialUnloadDataItem : InterfaceDataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "MATERIAL_UNLOAD";
public const string NameId = "materialUnload";
-
- public new const string DescriptionText = "Operating state of the service to unload a piece of material or product.";
+ public new const string DescriptionText = "Operating state of the service to unload a piece of material or product.";
+
public override string TypeDescription => DescriptionText;
- public override System.Version MinimumVersion => MTConnectVersions.Version13;
+ public override System.Version MinimumVersion => MTConnectVersions.Version13;
+
+
+ public new enum SubTypes
+ {
+ ///
+ /// Operating state of the request to unload a piece of material or product.
+ ///
+ REQUEST,
+
+ ///
+ /// Operating state of the response to a request to unload a piece of material or product.
+ ///
+ RESPONSE
+ }
public MaterialUnloadDataItem()
@@ -28,12 +42,43 @@ public MaterialUnloadDataItem()
}
- public MaterialUnloadDataItem(string deviceId)
+ public MaterialUnloadDataItem(
+ string parentId,
+ SubTypes subType
+ )
{
- Id = CreateId(deviceId, NameId);
+ Id = CreateId(parentId, NameId, GetSubTypeId(subType));
Category = CategoryId;
Type = TypeId;
+ SubType = subType.ToString();
Name = NameId;
+
}
+
+ public override string SubTypeDescription => GetSubTypeDescription(SubType);
+
+ public new static string GetSubTypeDescription(string subType)
+ {
+ var s = subType.ConvertEnum();
+ switch (s)
+ {
+ case SubTypes.REQUEST: return "Operating state of the request to unload a piece of material or product.";
+ case SubTypes.RESPONSE: return "Operating state of the response to a request to unload a piece of material or product.";
+ }
+
+ return null;
+ }
+
+ public new static string GetSubTypeId(SubTypes subType)
+ {
+ switch (subType)
+ {
+ case SubTypes.REQUEST: return "REQUEST";
+ case SubTypes.RESPONSE: return "RESPONSE";
+ }
+
+ return null;
+ }
+
}
-}
\ No newline at end of file
+}
diff --git a/libraries/MTConnect.NET-Common/Interfaces/OpenChuckDataItem.g.cs b/libraries/MTConnect.NET-Common/Interfaces/OpenChuckDataItem.g.cs
index ae06c54e8..7527290f5 100644
--- a/libraries/MTConnect.NET-Common/Interfaces/OpenChuckDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Interfaces/OpenChuckDataItem.g.cs
@@ -13,12 +13,26 @@ public class OpenChuckDataItem : InterfaceDataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "OPEN_CHUCK";
public const string NameId = "openChuck";
-
- public new const string DescriptionText = "Operating state of the service to open a chuck.";
+ public new const string DescriptionText = "Operating state of the service to open a chuck.";
+
public override string TypeDescription => DescriptionText;
- public override System.Version MinimumVersion => MTConnectVersions.Version13;
+ public override System.Version MinimumVersion => MTConnectVersions.Version13;
+
+
+ public new enum SubTypes
+ {
+ ///
+ /// Operating state of the request to open a chuck.
+ ///
+ REQUEST,
+
+ ///
+ /// Operating state of the response to a request to open a chuck.
+ ///
+ RESPONSE
+ }
public OpenChuckDataItem()
@@ -28,12 +42,43 @@ public OpenChuckDataItem()
}
- public OpenChuckDataItem(string deviceId)
+ public OpenChuckDataItem(
+ string parentId,
+ SubTypes subType
+ )
{
- Id = CreateId(deviceId, NameId);
+ Id = CreateId(parentId, NameId, GetSubTypeId(subType));
Category = CategoryId;
Type = TypeId;
+ SubType = subType.ToString();
Name = NameId;
+
}
+
+ public override string SubTypeDescription => GetSubTypeDescription(SubType);
+
+ public new static string GetSubTypeDescription(string subType)
+ {
+ var s = subType.ConvertEnum();
+ switch (s)
+ {
+ case SubTypes.REQUEST: return "Operating state of the request to open a chuck.";
+ case SubTypes.RESPONSE: return "Operating state of the response to a request to open a chuck.";
+ }
+
+ return null;
+ }
+
+ public new static string GetSubTypeId(SubTypes subType)
+ {
+ switch (subType)
+ {
+ case SubTypes.REQUEST: return "REQUEST";
+ case SubTypes.RESPONSE: return "RESPONSE";
+ }
+
+ return null;
+ }
+
}
-}
\ No newline at end of file
+}
diff --git a/libraries/MTConnect.NET-Common/Interfaces/OpenDoorDataItem.g.cs b/libraries/MTConnect.NET-Common/Interfaces/OpenDoorDataItem.g.cs
index 373cc5900..2103ddbe4 100644
--- a/libraries/MTConnect.NET-Common/Interfaces/OpenDoorDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Interfaces/OpenDoorDataItem.g.cs
@@ -13,12 +13,26 @@ public class OpenDoorDataItem : InterfaceDataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "OPEN_DOOR";
public const string NameId = "openDoor";
-
- public new const string DescriptionText = "Operating state of the service to open a door.";
+ public new const string DescriptionText = "Operating state of the service to open a door.";
+
public override string TypeDescription => DescriptionText;
- public override System.Version MinimumVersion => MTConnectVersions.Version13;
+ public override System.Version MinimumVersion => MTConnectVersions.Version13;
+
+
+ public new enum SubTypes
+ {
+ ///
+ /// Operating state of the request to open a door.
+ ///
+ REQUEST,
+
+ ///
+ /// Operating state of the response to a request to open a door.
+ ///
+ RESPONSE
+ }
public OpenDoorDataItem()
@@ -28,12 +42,43 @@ public OpenDoorDataItem()
}
- public OpenDoorDataItem(string deviceId)
+ public OpenDoorDataItem(
+ string parentId,
+ SubTypes subType
+ )
{
- Id = CreateId(deviceId, NameId);
+ Id = CreateId(parentId, NameId, GetSubTypeId(subType));
Category = CategoryId;
Type = TypeId;
+ SubType = subType.ToString();
Name = NameId;
+
}
+
+ public override string SubTypeDescription => GetSubTypeDescription(SubType);
+
+ public new static string GetSubTypeDescription(string subType)
+ {
+ var s = subType.ConvertEnum();
+ switch (s)
+ {
+ case SubTypes.REQUEST: return "Operating state of the request to open a door.";
+ case SubTypes.RESPONSE: return "Operating state of the response to a request to open a door.";
+ }
+
+ return null;
+ }
+
+ public new static string GetSubTypeId(SubTypes subType)
+ {
+ switch (subType)
+ {
+ case SubTypes.REQUEST: return "REQUEST";
+ case SubTypes.RESPONSE: return "RESPONSE";
+ }
+
+ return null;
+ }
+
}
-}
\ No newline at end of file
+}
diff --git a/libraries/MTConnect.NET-Common/Interfaces/PartChangeDataItem.g.cs b/libraries/MTConnect.NET-Common/Interfaces/PartChangeDataItem.g.cs
index 48da79dbf..5eddfd8e7 100644
--- a/libraries/MTConnect.NET-Common/Interfaces/PartChangeDataItem.g.cs
+++ b/libraries/MTConnect.NET-Common/Interfaces/PartChangeDataItem.g.cs
@@ -13,12 +13,26 @@ public class PartChangeDataItem : InterfaceDataItem
public const DataItemCategory CategoryId = DataItemCategory.EVENT;
public const string TypeId = "PART_CHANGE";
public const string NameId = "partChange";
-
- public new const string DescriptionText = "Operating state of the service to change the part or product associated with a piece of equipment to a different part or product.";
+ public new const string DescriptionText = "Operating state of the service to change the part or product associated with a piece of equipment to a different part or product.";
+
public override string TypeDescription => DescriptionText;
- public override System.Version MinimumVersion => MTConnectVersions.Version13;
+ public override System.Version MinimumVersion => MTConnectVersions.Version13;
+
+
+ public new enum SubTypes
+ {
+ ///
+ /// Operating state of the request to change the part or product associated with a piece of equipment to a different part or product.
+ ///
+ REQUEST,
+
+ ///
+ /// Operating state of the response to a request to change the part or product associated with a piece of equipment to a different part or product.
+ ///
+ RESPONSE
+ }
public PartChangeDataItem()
@@ -28,12 +42,43 @@ public PartChangeDataItem()
}
- public PartChangeDataItem(string deviceId)
+ public PartChangeDataItem(
+ string parentId,
+ SubTypes subType
+ )
{
- Id = CreateId(deviceId, NameId);
+ Id = CreateId(parentId, NameId, GetSubTypeId(subType));
Category = CategoryId;
Type = TypeId;
+ SubType = subType.ToString();
Name = NameId;
+
}
+
+ public override string SubTypeDescription => GetSubTypeDescription(SubType);
+
+ public new static string GetSubTypeDescription(string subType)
+ {
+ var s = subType.ConvertEnum();
+ switch (s)
+ {
+ case SubTypes.REQUEST: return "Operating state of the request to change the part or product associated with a piece of equipment to a different part or product.";
+ case SubTypes.RESPONSE: return "Operating state of the response to a request to change the part or product associated with a piece of equipment to a different part or product.";
+ }
+
+ return null;
+ }
+
+ public new static string GetSubTypeId(SubTypes subType)
+ {
+ switch (subType)
+ {
+ case SubTypes.REQUEST: return "REQUEST";
+ case SubTypes.RESPONSE: return "RESPONSE";
+ }
+
+ return null;
+ }
+
}
-}
\ No newline at end of file
+}
diff --git a/libraries/MTConnect.NET-SysML/Models/Assets/MTConnectAssetInformationModel.cs b/libraries/MTConnect.NET-SysML/Models/Assets/MTConnectAssetInformationModel.cs
index 37e1cdb58..6c3469afe 100644
--- a/libraries/MTConnect.NET-SysML/Models/Assets/MTConnectAssetInformationModel.cs
+++ b/libraries/MTConnect.NET-SysML/Models/Assets/MTConnectAssetInformationModel.cs
@@ -196,24 +196,42 @@ private void ParsePallets(XmiDocument xmiDocument, UmlPackage umlPackage)
// Pallets.Classes.AddRange(assetClasses);
//}
- // Add Measurement Classes
+ // Add Measurement Classes via the rich measurement pipeline
+ // (mirrors the CuttingTool path at line 119) so each Pallet
+ // measurement subclass renders with TypeId / CodeId /
+ // three-ctor scaffolding rather than the bare ClassModel
+ // shape. Filter out the abstract `Measurement` class itself
+ // (MTConnectMeasurementModel auto-suffixes "Measurement",
+ // which would otherwise produce `MeasurementMeasurement`).
var packages = new List();
packages.Add(targetPackage.Packages.FirstOrDefault(o => o.Name == "Measurements"));
- var umlClasses = ModelHelper.GetClasses(packages);
- var measurementClasses = MTConnectClassModel.Parse(xmiDocument, "Assets.Pallet", umlClasses);
+ var allMeasurementClasses = ModelHelper.GetClasses(packages);
+ var concreteMeasurementClasses = allMeasurementClasses
+ ?.Where(c => c.Name != "Measurement");
+ var measurementClasses = MTConnectMeasurementModel.Parse(
+ xmiDocument, "PhysicalAsset", "Assets.Pallet", concreteMeasurementClasses);
if (measurementClasses != null)
{
- foreach (var measurementClass in measurementClasses)
+ Pallets.Classes.AddRange(measurementClasses);
+ }
+
+ // Also parse the abstract `Measurement` base class itself via
+ // the regular class pipeline so it can be regenerated as a
+ // partial class (see TemplateRenderer override). The concrete
+ // subclasses' `Measurement(IMeasurement)` ctor needs the base
+ // partial to provide the copy-from-IMeasurement ctor + the
+ // `Type` property the rich template emits.
+ var abstractMeasurement = allMeasurementClasses
+ ?.Where(c => c.Name == "Measurement");
+ if (abstractMeasurement != null)
+ {
+ var baseMeasurementClasses = MTConnectClassModel.Parse(
+ xmiDocument, "Assets.Pallet", abstractMeasurement);
+ if (baseMeasurementClasses != null)
{
- if (measurementClass.Id != "Assets.Pallet.Measurement")
- {
- measurementClass.Id = $"{measurementClass.Id}Measurement";
- measurementClass.Name = $"{measurementClass.Name}Measurement";
- }
+ Pallets.Classes.AddRange(baseMeasurementClasses);
}
-
- Pallets.Classes.AddRange(measurementClasses);
}
diff --git a/libraries/MTConnect.NET-SysML/Models/Devices/MTConnectDataItemType.cs b/libraries/MTConnect.NET-SysML/Models/Devices/MTConnectDataItemType.cs
index 95cee0433..c68704859 100644
--- a/libraries/MTConnect.NET-SysML/Models/Devices/MTConnectDataItemType.cs
+++ b/libraries/MTConnect.NET-SysML/Models/Devices/MTConnectDataItemType.cs
@@ -62,7 +62,7 @@ public MTConnectDataItemType(XmiDocument xmiDocument, string category, string id
Type = umlEnumerationLiteral.Name;
//Type = umlClass.Name.ToUnderscoreUpper();
- var description = umlEnumerationLiteral.Comments?.FirstOrDefault().Body;
+ var description = umlEnumerationLiteral.Comments?.FirstOrDefault()?.Body;
Description = ModelHelper.ProcessDescription(description);
MaximumVersion = MTConnectVersion.LookupDeprecated(xmiDocument, umlClass.Id);
@@ -78,6 +78,22 @@ public MTConnectDataItemType(XmiDocument xmiDocument, string category, string id
//if (ParentName != null && ParentName != "DataItem") ParentName += "DataItem";
}
+ // The MTConnect SysML model declares a DataItem's
+ // representation in two complementary places:
+ // * the typing of its `result` property (a DataType
+ // for VALUE; a Class with key/value sub-properties
+ // for the structured forms), and
+ // * the prose marker that the matching EventEnum
+ // literal carries on its description, of the
+ // form `{{term(data set)}}` / `{{term(table)}}`
+ // / `{{term(time series)}}` at the start of the
+ // comment body.
+ // Read the prose marker first so DataItems whose
+ // structured representation is encoded only in the
+ // enum-literal description (ASSET_COUNT being the
+ // canonical example) inherit the correct default.
+ var representationFromEnum = GetRepresentationFromEnumLiteral(umlEnumerationLiteral);
+
if (umlClass.Properties != null)
{
foreach (var property in umlClass.Properties)
@@ -95,7 +111,17 @@ public MTConnectDataItemType(XmiDocument xmiDocument, string category, string id
// Result
if (property.Name == "result")
{
- // Get Class (TABLE OR DATA_SET)
+ // Get Class (structured result). The MTConnect
+ // SysML model encodes the canonical structured
+ // representation in the parent chain of the
+ // result class — `DataSet` for one-dimensional
+ // key/value rows, `Table` for two-dimensional
+ // key/value matrices, `TimeSeries` for sample
+ // sequences. Walk the chain to pick the right
+ // representation; fall back to TABLE so result
+ // classes whose generalization terminates in a
+ // template-binding (e.g. WORK_OFFSETS,
+ // TOOL_OFFSETS) keep their existing default.
Result = ModelHelper.GetClassName(xmiDocument, property.PropertyType);
if (Result == null)
@@ -106,7 +132,7 @@ public MTConnectDataItemType(XmiDocument xmiDocument, string category, string id
}
else
{
- Representation = "TABLE"; // Should probably take into account DATA_SET as well?
+ Representation = ResolveStructuredRepresentation(xmiDocument, property.PropertyType);
}
}
@@ -126,6 +152,15 @@ public MTConnectDataItemType(XmiDocument xmiDocument, string category, string id
}
}
+ // Enum-literal prose wins over the result-class fallback:
+ // the SysML XMI uses it as the authoritative marker for the
+ // canonical representation of types whose result property
+ // points at a primitive DataType.
+ if (representationFromEnum != null)
+ {
+ Representation = representationFromEnum;
+ }
+
if (subClasses != null)
{
var subTypes = new List();
@@ -183,6 +218,62 @@ private static string ConvertClassName(string name)
return null;
}
+ // Walk the generalization chain of a result class to pick the
+ // structured representation it encodes. The MTConnect SysML
+ // model defines three abstract result-shape parents:
+ // `DataSet`, `Table`, and `TimeSeries`; concrete result classes
+ // (e.g. AlarmLimitResult, FeatureMeasurementResult) generalize
+ // from one of them. A class with no chain match falls back to
+ // TABLE so result classes whose generalization terminates in a
+ // template-binding (e.g. WORK_OFFSETS, TOOL_OFFSETS) keep their
+ // existing default.
+ //
+ // The walk is bounded by a visited-set rather than a depth cap
+ // because a malformed XMI cycle would otherwise loop forever;
+ // the visited-set both detects cycles and short-circuits a
+ // diamond-inheritance graph that visits the same parent twice.
+ private static string ResolveStructuredRepresentation(XmiDocument xmiDocument, string resultClassId)
+ {
+ var visited = new HashSet();
+ var current = ModelHelper.GetClass(xmiDocument, resultClassId);
+ while (current != null && visited.Add(current.Id))
+ {
+ switch (current.Name)
+ {
+ case "DataSet": return "DATA_SET";
+ case "Table": return "TABLE";
+ case "TimeSeries": return "TIME_SERIES";
+ }
+
+ var parentId = current.Generalizations?.FirstOrDefault()?.General;
+ if (string.IsNullOrEmpty(parentId)) break;
+ current = ModelHelper.GetClass(xmiDocument, parentId);
+ }
+
+ return "TABLE";
+ }
+
+ // The MTConnect SysML model embeds the canonical representation
+ // of an EventEnum literal in its description. The marker is one
+ // of `{{term(data set)}}`, `{{term(table)}}`, or
+ // `{{term(time series)}}` and appears at the start of the
+ // comment body. When present, it overrides the result-property
+ // typing fallback so DataItems whose `result` references a
+ // primitive DataType (e.g. ASSET_COUNT pointing at `integer`)
+ // still inherit the structured representation the spec mandates.
+ private static string GetRepresentationFromEnumLiteral(UmlEnumerationLiteral umlEnumerationLiteral)
+ {
+ var body = umlEnumerationLiteral?.Comments?.FirstOrDefault()?.Body;
+ if (string.IsNullOrEmpty(body)) return null;
+
+ var trimmed = body.TrimStart();
+ if (trimmed.StartsWith("{{term(data set)}}")) return "DATA_SET";
+ if (trimmed.StartsWith("{{term(table)}}")) return "TABLE";
+ if (trimmed.StartsWith("{{term(time series)}}")) return "TIME_SERIES";
+
+ return null;
+ }
+
private static string ConvertEnumName(string name)
{
if (name != null)
diff --git a/tests/MTConnect.NET-Common-Tests/Agents/AssetCountAutoGeneratedDataSetTests.cs b/tests/MTConnect.NET-Common-Tests/Agents/AssetCountAutoGeneratedDataSetTests.cs
new file mode 100644
index 000000000..25c11b8b9
--- /dev/null
+++ b/tests/MTConnect.NET-Common-Tests/Agents/AssetCountAutoGeneratedDataSetTests.cs
@@ -0,0 +1,87 @@
+// Copyright (c) 2026 TrakHound Inc., All Rights Reserved.
+// TrakHound Inc. licenses this file to you under the MIT license.
+
+using System.Linq;
+using MTConnect.Agents;
+using MTConnect.Devices;
+using MTConnect.Devices.DataItems;
+using NUnit.Framework;
+
+namespace MTConnect.Tests.Common.Agents
+{
+ ///
+ /// Asserts that the auto-injected ASSET_COUNT DataItem carries the
+ /// MTConnect-mandated DATA_SET representation.
+ ///
+ /// MTConnect Standard, Part 2 — Devices Information Model, defines
+ /// ASSET_COUNT (UML element ID
+ /// _19_0_3_68e0225_1640602520420_217627_44, also captured in
+ /// AssetCountDataItem.g.cs) as a DATA_SET representation: a map of
+ /// asset-type to the count of assets of that type currently held in
+ /// the agent's asset buffer. The agent auto-injects an
+ /// AssetCountDataItem when normalising a device, and that injection
+ /// must produce a DataItem whose Representation is DATA_SET so the
+ /// resulting Probe matches the spec.
+ ///
+ [TestFixture]
+ [Category("AssetCountIsDataSet")]
+ public class AssetCountAutoGeneratedDataSetTests
+ {
+ [Test]
+ public void AutoInjected_AssetCount_Has_DataSet_Representation()
+ {
+ using var agent = new MTConnectAgent(initializeAgentDevice: false);
+
+ var device = new Device
+ {
+ Id = "dev",
+ Name = "dev",
+ Uuid = "dev-uuid"
+ };
+
+ var added = agent.AddDevice(device, initializeDataItems: false);
+
+ Assert.That(added, Is.Not.Null);
+
+ var assetCount = added.DataItems
+ .SingleOrDefault(d => d.Type == AssetCountDataItem.TypeId);
+
+ Assert.That(assetCount, Is.Not.Null,
+ "auto-generator must inject one ASSET_COUNT DataItem");
+ Assert.That(assetCount!.Representation,
+ Is.EqualTo(DataItemRepresentation.DATA_SET),
+ "auto-injected ASSET_COUNT must carry DATA_SET representation per MTConnect Part 2");
+ }
+
+ [Test]
+ public void UserDeclared_AssetCount_Representation_Is_Preserved()
+ {
+ using var agent = new MTConnectAgent(initializeAgentDevice: false);
+
+ var declared = new AssetCountDataItem("dev")
+ {
+ Representation = DataItemRepresentation.VALUE
+ };
+
+ var device = new Device
+ {
+ Id = "dev",
+ Name = "dev",
+ Uuid = "dev-uuid",
+ DataItems = new[] { declared }
+ };
+
+ var added = agent.AddDevice(device, initializeDataItems: false);
+
+ Assert.That(added, Is.Not.Null);
+
+ var assetCount = added.DataItems
+ .SingleOrDefault(d => d.Type == AssetCountDataItem.TypeId);
+
+ Assert.That(assetCount, Is.Not.Null);
+ Assert.That(assetCount!.Representation,
+ Is.EqualTo(DataItemRepresentation.VALUE),
+ "user-declared ASSET_COUNT representation must be preserved verbatim");
+ }
+ }
+}
diff --git a/tests/MTConnect.NET-Common-Tests/Agents/AssetCountFactoryDataSetGuardTests.cs b/tests/MTConnect.NET-Common-Tests/Agents/AssetCountFactoryDataSetGuardTests.cs
new file mode 100644
index 000000000..557258f46
--- /dev/null
+++ b/tests/MTConnect.NET-Common-Tests/Agents/AssetCountFactoryDataSetGuardTests.cs
@@ -0,0 +1,116 @@
+// Copyright (c) 2026 TrakHound Inc., All Rights Reserved.
+// TrakHound Inc. licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MTConnect.Agents;
+using MTConnect.Configurations;
+using MTConnect.Devices;
+using MTConnect.Devices.DataItems;
+using NUnit.Framework;
+
+namespace MTConnect.Tests.Common.Agents
+{
+ ///
+ /// Regression pin for
+ /// https://github.com/TrakHound/MTConnect.NET/issues/132 :
+ /// every code path that auto-injects an AssetCountDataItem MUST
+ /// stamp Representation = DATA_SET. The defect was an auto-generator
+ /// that inherited the .g.cs DefaultRepresentation = VALUE; this
+ /// fixture guards every auto-injection entry point we have access
+ /// to so a future regenerated generator (or a refactor of
+ /// NormalizeDevice) cannot reintroduce the bug silently.
+ ///
+ /// Spec: MTConnect Standard, Part 2 - Devices Information Model,
+ /// ASSET_COUNT (UML _19_0_3_68e0225_1640602520420_217627_44).
+ ///
+ [TestFixture]
+ [Category("AssetCountIsDataSet")]
+ public class AssetCountFactoryDataSetGuardTests
+ {
+ private static readonly string[] _deviceIds = { "lathe-1", "mill-7", "robot-A" };
+
+ [TestCaseSource(nameof(_deviceIds))]
+ public void AddDevice_AutoInjects_AssetCount_With_DataSet_Representation(string deviceId)
+ {
+ using var agent = new MTConnectAgent(initializeAgentDevice: false);
+
+ var device = new Device
+ {
+ Id = deviceId,
+ Name = deviceId,
+ Uuid = $"{deviceId}-uuid"
+ };
+
+ var added = agent.AddDevice(device, initializeDataItems: false);
+
+ Assert.That(added, Is.Not.Null);
+
+ var assetCount = added.DataItems
+ .SingleOrDefault(d => d.Type == AssetCountDataItem.TypeId);
+
+ Assert.That(assetCount, Is.Not.Null,
+ "auto-generator must inject one ASSET_COUNT DataItem on every device");
+ Assert.That(assetCount!.Representation,
+ Is.EqualTo(DataItemRepresentation.DATA_SET));
+ }
+
+ [Test]
+ public void AddDevices_AutoInjects_AssetCount_With_DataSet_Representation_For_Every_Device()
+ {
+ using var agent = new MTConnectAgent(initializeAgentDevice: false);
+
+ var devices = _deviceIds.Select(id => new Device
+ {
+ Id = id,
+ Name = id,
+ Uuid = $"{id}-uuid"
+ }).ToList();
+
+ var added = agent.AddDevices(devices, initializeDataItems: false);
+
+ Assert.That(added, Is.Not.Null);
+ Assert.That(added.Count(), Is.EqualTo(_deviceIds.Length));
+
+ foreach (var dev in added)
+ {
+ var assetCount = dev.DataItems
+ .SingleOrDefault(d => d.Type == AssetCountDataItem.TypeId);
+
+ Assert.That(assetCount, Is.Not.Null,
+ $"device {dev.Id}: auto-generator must inject one ASSET_COUNT DataItem");
+ Assert.That(assetCount!.Representation,
+ Is.EqualTo(DataItemRepresentation.DATA_SET),
+ $"device {dev.Id}: Representation must be DATA_SET");
+ }
+ }
+
+ [Test]
+ public void AddDevice_With_Configuration_AutoInjects_AssetCount_With_DataSet_Representation()
+ {
+ // Same agent path but constructed via the configuration overload
+ // to keep both constructor paths covered.
+ var configuration = new AgentConfiguration();
+ using var agent = new MTConnectAgent(configuration, initializeAgentDevice: false);
+
+ var device = new Device
+ {
+ Id = "configured-dev",
+ Name = "configured-dev",
+ Uuid = "configured-dev-uuid"
+ };
+
+ var added = agent.AddDevice(device, initializeDataItems: false);
+
+ Assert.That(added, Is.Not.Null);
+
+ var assetCount = added.DataItems
+ .SingleOrDefault(d => d.Type == AssetCountDataItem.TypeId);
+
+ Assert.That(assetCount, Is.Not.Null);
+ Assert.That(assetCount!.Representation,
+ Is.EqualTo(DataItemRepresentation.DATA_SET));
+ }
+ }
+}
diff --git a/tests/MTConnect.NET-Common-Tests/Assets/Pallet/PalletMeasurementContractTests.cs b/tests/MTConnect.NET-Common-Tests/Assets/Pallet/PalletMeasurementContractTests.cs
new file mode 100644
index 000000000..8d87303e8
--- /dev/null
+++ b/tests/MTConnect.NET-Common-Tests/Assets/Pallet/PalletMeasurementContractTests.cs
@@ -0,0 +1,196 @@
+// Copyright (c) 2026 TrakHound Inc., All Rights Reserved.
+// TrakHound Inc. licenses this file to you under the MIT license.
+
+using System;
+using System.Linq;
+using System.Reflection;
+using MTConnect.Assets.Pallet;
+using NUnit.Framework;
+
+namespace MTConnect.Tests.Common.Assets.Pallet
+{
+ ///
+ /// Pins the class-level contract that every Pallet measurement
+ /// subclass renders with the rich TypeId + three-constructor
+ /// scaffolding produced by the SysML measurement template, in
+ /// parity with the long-standing CuttingTools measurement DTOs.
+ ///
+ /// Per the MTConnect SysML model, the PhysicalAsset > Pallet
+ /// > Measurements package declares ten concrete measurement
+ /// subclasses (Weight, Height, Width, Length, Swing plus their
+ /// Loaded* counterparts) that generalize from an abstract
+ /// Measurement base. The C# generator must emit each one
+ /// with:
+ ///
+ /// a const string TypeId equal to the SysML class name;
+ /// a default constructor that stamps Type = TypeId;
+ /// a (double value) constructor that stamps both
+ /// Type and Value;
+ /// a (IMeasurement) copy constructor chaining to
+ /// the partial base.
+ ///
+ ///
+ /// Sources:
+ /// - SysML XMI:
+ /// v2.7. The Pallet measurement subclasses sit under UML package
+ /// "Asset Information Model > Pallet > Measurements" with the
+ /// abstract base UML ID
+ /// _2024x_68e0225_1727793846441_986747_23754.
+ /// - Reference implementation: cppagent's generic
+ /// PhysicalAsset::getMeasurementsFactory() handles every
+ /// physical-asset measurement element via a single regex-matched
+ /// factory; the per-type DTO scaffolding is a .NET-side ergonomic
+ /// convenience that mirrors what CuttingTools already gets.
+ ///
+ [TestFixture]
+ [Category("PalletMeasurementContract")]
+ public class PalletMeasurementContractTests
+ {
+ private static readonly (Type Type, string ExpectedTypeId)[] _palletMeasurements = new[]
+ {
+ (typeof(WeightMeasurement), "Weight"),
+ (typeof(HeightMeasurement), "Height"),
+ (typeof(WidthMeasurement), "Width"),
+ (typeof(LengthMeasurement), "Length"),
+ (typeof(SwingMeasurement), "Swing"),
+ (typeof(LoadedWeightMeasurement), "LoadedWeight"),
+ (typeof(LoadedHeightMeasurement), "LoadedHeight"),
+ (typeof(LoadedWidthMeasurement), "LoadedWidth"),
+ (typeof(LoadedLengthMeasurement), "LoadedLength"),
+ (typeof(LoadedSwingMeasurement), "LoadedSwing"),
+ };
+
+ private static System.Collections.Generic.IEnumerable PalletMeasurementCases =>
+ _palletMeasurements.Select(p => new TestCaseData(p.Type, p.ExpectedTypeId)
+ .SetName($"{{m}}({p.Type.Name})"));
+
+ [Test]
+ [TestCaseSource(nameof(PalletMeasurementCases))]
+ public void TypeId_Const_Equals_SysML_ClassName(Type measurementType, string expectedTypeId)
+ {
+ // The TypeId const is the wire-side discriminator the
+ // serializer uses to round-trip the measurement element
+ // name. It must equal the SysML class name verbatim.
+ var field = measurementType.GetField(
+ "TypeId",
+ BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
+
+ Assert.That(field, Is.Not.Null,
+ $"{measurementType.Name} must expose a public static TypeId const field");
+ Assert.That(field!.IsLiteral, Is.True,
+ $"{measurementType.Name}.TypeId must be a const literal");
+ Assert.That(field.FieldType, Is.EqualTo(typeof(string)),
+ $"{measurementType.Name}.TypeId must be a string");
+ Assert.That(field.GetRawConstantValue(), Is.EqualTo(expectedTypeId),
+ $"{measurementType.Name}.TypeId must equal '{expectedTypeId}'");
+ }
+
+ [Test]
+ [TestCaseSource(nameof(PalletMeasurementCases))]
+ public void CodeId_Const_Is_Empty(Type measurementType, string expectedTypeId)
+ {
+ // Pallet measurements carry no MeasurementCode (the SysML
+ // Pallet Measurement abstract class has no `code` property,
+ // unlike the CuttingTool ToolingMeasurement which binds to
+ // MeasurementCodeEnum). The CodeId const must therefore be
+ // emitted as the empty string.
+ var field = measurementType.GetField(
+ "CodeId",
+ BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
+
+ Assert.That(field, Is.Not.Null,
+ $"{measurementType.Name} must expose a public static CodeId const field");
+ Assert.That(field!.IsLiteral, Is.True,
+ $"{measurementType.Name}.CodeId must be a const literal");
+ Assert.That(field.GetRawConstantValue(), Is.EqualTo(string.Empty),
+ $"{measurementType.Name}.CodeId must be empty for Pallet measurements");
+ }
+
+ [Test]
+ [TestCaseSource(nameof(PalletMeasurementCases))]
+ public void Default_Constructor_Stamps_Type(Type measurementType, string expectedTypeId)
+ {
+ var ctor = measurementType.GetConstructor(Type.EmptyTypes);
+ Assert.That(ctor, Is.Not.Null,
+ $"{measurementType.Name} must declare a public default constructor");
+
+ var instance = (Measurement)ctor!.Invoke(Array.Empty