Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
12 changes: 11 additions & 1 deletion MTConnect.NET.sln
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MTConnect.NET-XML-Tests", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MTConnect.NET-SysML-Import", "build\MTConnect.NET-SysML-Import\MTConnect.NET-SysML-Import.csproj", "{C5F7C26D-F394-42F6-852B-C6981A99AA0F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MTConnect.NET-SysML-Import-Tests", "tests\MTConnect.NET-SysML-Import-Tests\MTConnect.NET-SysML-Import-Tests.csproj", "{9B5A2D9F-1E4C-4F8B-A7D2-3E6C8B4F2A9D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MTConnect.NET-AgentProcessor-Python", "agent\Processors\MTConnect.NET-AgentProcessor-Python\MTConnect.NET-AgentProcessor-Python.csproj", "{F6FDE58F-6520-4BFB-9587-A7FF66628AD8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MTConnect.NET-AgentModule-MqttRelay", "agent\Modules\MTConnect.NET-AgentModule-MqttRelay\MTConnect.NET-AgentModule-MqttRelay.csproj", "{CB2E7F5A-55D5-43BD-ABC8-145E8436BE88}"
Expand Down Expand Up @@ -295,6 +297,14 @@ Global
{8AD3DE52-3EC4-49BC-B512-9976477C1E63}.Package|Any CPU.Build.0 = Debug|Any CPU
{8AD3DE52-3EC4-49BC-B512-9976477C1E63}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8AD3DE52-3EC4-49BC-B512-9976477C1E63}.Release|Any CPU.Build.0 = Release|Any CPU
{9B5A2D9F-1E4C-4F8B-A7D2-3E6C8B4F2A9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9B5A2D9F-1E4C-4F8B-A7D2-3E6C8B4F2A9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B5A2D9F-1E4C-4F8B-A7D2-3E6C8B4F2A9D}.Docker|Any CPU.ActiveCfg = Debug|Any CPU
{9B5A2D9F-1E4C-4F8B-A7D2-3E6C8B4F2A9D}.Docker|Any CPU.Build.0 = Debug|Any CPU
{9B5A2D9F-1E4C-4F8B-A7D2-3E6C8B4F2A9D}.Package|Any CPU.ActiveCfg = Debug|Any CPU
{9B5A2D9F-1E4C-4F8B-A7D2-3E6C8B4F2A9D}.Package|Any CPU.Build.0 = Debug|Any CPU
{9B5A2D9F-1E4C-4F8B-A7D2-3E6C8B4F2A9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B5A2D9F-1E4C-4F8B-A7D2-3E6C8B4F2A9D}.Release|Any CPU.Build.0 = Release|Any CPU
{C5F7C26D-F394-42F6-852B-C6981A99AA0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C5F7C26D-F394-42F6-852B-C6981A99AA0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5F7C26D-F394-42F6-852B-C6981A99AA0F}.Docker|Any CPU.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -576,7 +586,7 @@ Global
{17E64F59-0E62-4FCE-BEC4-EABBCF95B9A2} = {BBF53739-168D-4635-8595-083AC0C65E4C}
{AE09D1CA-5572-40BF-B984-74230E8634E1} = {14375E03-6BF8-45E6-B868-D2399368992B}
{3E89B860-A428-470C-8E48-0DDABC4027F0} = {14375E03-6BF8-45E6-B868-D2399368992B}
{6CE969D2-A1E8-4BC1-85D8-303701B42F64} = {14375E03-6BF8-45E6-B868-D2399368992B}
{9B5A2D9F-1E4C-4F8B-A7D2-3E6C8B4F2A9D} = {14375E03-6BF8-45E6-B868-D2399368992B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CC13D3AD-18BF-4695-AB2A-087EF0885B20}
Expand Down
33 changes: 15 additions & 18 deletions build/MTConnect.NET-SysML-Import/CSharp/TemplateRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -299,11 +299,10 @@ public static void Render(MTConnectModel mtconnectModel, string outputPath)
//
// The full import-side classModels list is passed too so the
// walk can find parents that are present in the SysML graph but
// never reach `templates` (e.g. `Assets.CuttingTools.Measurement`,
// an abstract base whose .g.cs is hand-maintained / frozen and
// therefore not re-emitted by any current renderer flow). The
// child ToolingMeasurement still extends it at C# compile time,
// so its `Code` property hides Measurement.Code and needs `new`.
// never reach `templates` (e.g. abstract bases whose .g.cs is
// hand-maintained / frozen and therefore not re-emitted by any
// current renderer flow) — the child class still extends them at
// C# compile time, so any name collision needs the `new` marker.
MarkInheritedProperties(templates, classModels);


Expand Down Expand Up @@ -490,7 +489,7 @@ private static void WriteDescriptions(ITemplateModel template, string outputPath
/// <see cref="MTConnectClassModel.ParentName"/> through every
/// ClassModel the renderer has assembled. This catches the
/// overwhelming majority of cases (Asset.SerialNumber ⇒
/// CuttingToolAsset, Measurement.Code ⇒ ToolingMeasurement, etc.).
/// CuttingToolAsset, Component.Uuid ⇒ Device, etc.).
/// </item>
/// <item>
/// Hand-stitched seeds for inheritance links the SysML model does
Expand Down Expand Up @@ -644,18 +643,16 @@ private static void MarkInheritedProperties(
case "Assets.CuttingTools.ToolingMeasurement":
// ToolingMeasurement extends `Measurement` (the
// CuttingTools abstract Measurement base, NOT
// Assets.Pallet.Measurement). The CuttingTools
// Measurement.g.cs is hand-maintained / frozen —
// not produced by any current renderer flow — so
// it never enters the export-side ClassModel
// graph the inheritance walk traverses, and a
// Name-only lookup of "Measurement" resolves to
// Pallet.Measurement (which lacks Code). Class
// side only — IMeasurement.g.cs has `Code`
// commented out, so the interface child does NOT
// hide anything and emitting `new` there would
// produce CS0109 instead.
classOnlyNames.Add("Code");
// Assets.Pallet.Measurement). The SysML v2.7 XMI
// relocates `Code` onto ToolingMeasurement — the
// parent Measurement (both class and interface)
// no longer declares Code, so ToolingMeasurement's
// `Code` is a fresh introduction that hides
// nothing. Emitting `new` here would raise CS0109
// on both the class and the interface. No hand-
// stitched inheritance seed is needed for this
// template — leave the case block as a marker so
// the intentional emptiness is documented.
break;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,4 @@ namespace MTConnect.Assets.CuttingTools.Measurements
{{ if (units_enum) }}Units = {{units_enum}};{{ end }}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@ namespace MTConnect.Devices.Compositions
/// </summary>
public {{name}}() { Type = TypeId; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -270,4 +270,4 @@ namespace MTConnect.Devices.DataItems
}
{{- end }}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -764,4 +764,4 @@ namespace MTConnect.Devices
return null;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ namespace {{namespace}}
{{ end }}
{{- end }}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ namespace {{namespace}}
}
{{- end }}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ namespace {{namespace}}
{{ end }}
{{- end }}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ namespace {{namespace}}
}
{{- end }}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ namespace {{namespace}}
{{ end }}{{ end }}
{{- end }}
}
}
}
15 changes: 8 additions & 7 deletions build/MTConnect.NET-SysML-Import/CSharp/Templates/Model.scriban
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,16 @@ namespace {{namespace}}
{{- end }}{{ end }}
};
{{- end }}
{{ i = 0 }}{{- for property in properties }}{{ i = i + 1 }}

{{ for property in properties }}
/// <summary>
/// {{property.description}}
/// </summary>
{{ if (property.is_array) }}public {{ if (property.is_inherited) }}new {{ end }}System.Collections.Generic.IEnumerable<{{property.data_type}}> {{property.name}} { get; set; }{{ end }}
{{- if (!property.is_array) }}public {{ if (property.is_inherited) }}new {{ end }}{{property.data_type}}{{ if (property.is_optional) }}?{{ end }} {{property.name}} { get; set; }{{ end }}
{{- if (i < (properties | array.size)) }}
{{ end }}
{{- end }}
{{- if (property.is_array) }}
public {{ if (property.is_inherited) }}new {{ end }}System.Collections.Generic.IEnumerable<{{property.data_type}}> {{property.name}} { get; set; }
{{- else }}
public {{ if (property.is_inherited) }}new {{ end }}{{property.data_type}}{{ if (property.is_optional) }}?{{ end }} {{property.name}} { get; set; }
{{- end }}
{{ end ~}}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ namespace {{namespace}}
{{ end }}
{{- end }}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ namespace {{namespace}}
{{ end }}
{{- end }}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ namespace {{namespace}}
{{ end }}
{{- end }}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ namespace {{namespace}}
{{ if (units_enum) }}Units = {{units_enum}};{{ end }}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ namespace MTConnect.Assets.Xml.CuttingTools
{{- end }}
public List<XmlMeasurement> Measurements { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ namespace MTConnect.Assets.Xml.CuttingTools
{{- end }}
public List<XmlMeasurement> Measurements { get; set; }
}
}
}
1 change: 1 addition & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ export default withMermaid(
text: 'Migration notes',
items: [
{ text: 'v7: ValidationResult consolidation', link: '/migration/v7-validation-result' },
{ text: 'v7: CuttingTools Measurement.Code relocation', link: '/migration/v7-cuttingtools-measurement-code-relocation' },
],
},
],
Expand Down
4 changes: 4 additions & 0 deletions docs/concepts/assets.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ tool.CuttingToolLifeCycle = lifeCycle;

The `CuttingToolArchetypeAsset` variant (`Type == "CuttingToolArchetype"`) describes the tool's design-time blueprint — the shape every instance of the part-number-X conforms to — and the `CuttingToolAsset` references its archetype via `CuttingToolArchetypeReference`. Source: SysML `CuttingToolAsset` and `CuttingToolArchetype` classes ([`mtconnect/mtconnect_sysml_model`](https://github.com/mtconnect/mtconnect_sysml_model)).

::: tip v7 relocation — `Code` lives on `ToolingMeasurement`
As of v7, the `Code` property is no longer declared on the abstract `Measurement` base — it lives directly on the concrete `ToolingMeasurement` subclass. Non-tooling measurements (`CuttingDiameterMeasurement`, `WeightMeasurement`, the rest of the `Measurements.*` family) no longer expose `Code`, matching the SysML v2.7 XMI. See the [v7 CuttingTools Measurement.Code relocation](/migration/v7-cuttingtools-measurement-code-relocation) migration note for details and the compile-error resolution path.
:::

## Pallet

A `PalletAsset` describes a pallet on a transfer system: its dimensions, its loaded vs unloaded shape, the work-piece(s) currently on it. The MTConnect Standard introduced typed measurements for pallets in v2.4, replacing the earlier free-form `Measurement` element with concrete classes:
Expand Down
84 changes: 84 additions & 0 deletions docs/migration/v7-cuttingtools-measurement-code-relocation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
title: 'v7 migration: CuttingTools Measurement.Code relocation'
description: The MTConnect SysML v2.7 model moves the Code property from the abstract Measurement base onto the concrete ToolingMeasurement subclass. MTConnect.NET-Common's regenerated .g.cs surface follows suit and removes Measurement.Code.
---

# v7 migration: CuttingTools `Measurement.Code` relocation

Prior to v7, [`MTConnect.Assets.CuttingTools.Measurement`](/api/MTConnect.Assets.CuttingTools.Measurement) — the abstract base class every specific cutting-tool measurement inherits — carried a `Code` property. That was a legacy of the pre-2.7 SysML model, which declared `Code` on `Measurement` and let `ToolingMeasurement` inherit it.

MTConnect SysML v2.7 relocates `Code` off the base and onto the concrete [`ToolingMeasurement`](/api/MTConnect.Assets.CuttingTools.ToolingMeasurement) subclass. v7 of MTConnect.NET-Common regenerates the C# surface from the v2.7 XMI and follows the same relocation: `Measurement.Code` is removed, and `ToolingMeasurement.Code` becomes the sole home for the property.

## What changed

| Symbol | Pre-v7 | v7 |
| --- | --- | --- |
| `MTConnect.Assets.CuttingTools.Measurement.Code` | Present on the abstract base | **Removed** |
| `MTConnect.Assets.CuttingTools.ToolingMeasurement.Code` | Inherited from `Measurement` | Declared directly on `ToolingMeasurement` |

`Measurement.DescriptionText` is also reworded to match the v2.7 XMI phrasing; the class-level description string changes but the API shape does not.

Every concrete measurement class that inherited `Code` transitively via `Measurement` (`CuttingDiameterMeasurement`, `WeightMeasurement`, `WiperEdgeLengthMeasurement`, and the rest of the 40-odd `Measurements.*` family) loses the `Code` property. `ToolingMeasurement` and its subclasses are the only measurement family that continues to carry it, matching the SysML v2.7 shape.

## Migration table

| Before (pre-v7) | After (v7) |
| --- | --- |
| `CuttingDiameterMeasurement { Code = "x" }` — sets `Measurement.Code` | Not applicable — the property no longer exists on this class; drop the `Code` initialiser. |
| `WiperEdgeLengthMeasurement instance = …; instance.Code = "x";` | Not applicable — drop the assignment. |
| `Measurement m = …; string c = m.Code;` — reads through the base | Read `Code` off the concrete `ToolingMeasurement` instead: cast to `ToolingMeasurement` (or the concrete tooling-measurement class) and read from there. |
| `((Measurement)toolingMeasurement).Code` — up-cast read | `toolingMeasurement.Code` — the `ToolingMeasurement`-declared property is on the concrete type. |

Any code path that reached `Code` via the abstract `Measurement` type will fail to compile after upgrading. The compiler error points at the exact call sites; each one becomes either a delete (if the pre-v7 code was setting `Code` on a non-tooling measurement class where the value was silently ignored by the XML wire format) or a cast to the concrete `ToolingMeasurement` subclass.

## Why the relocation

The SysML v2.7 shape reflects how the wire format actually behaves: `Code` is a `ToolingMeasurement`-specific attribute in the XSD, and every non-tooling measurement class ignored the value at serialisation time. Hoisting the property onto the abstract base pre-v7 was a code-side convenience that let callers set `Code` on any measurement, but the value was dropped on write for every measurement family except `ToolingMeasurement`. Relocating the declaration onto the concrete subclass restores the pre-condition the spec always intended: only `ToolingMeasurement` (and its subclasses) carry a `Code`.

## Before / after — measurement author

```csharp
// Before (pre-v7) — Code is set on the base Measurement type;
// XML serialisation silently drops the value for non-tooling measurements
using MTConnect.Assets.CuttingTools.Measurements;

var diameter = new CuttingDiameterMeasurement
{
Value = 12.0m,
Code = "CD", // silently dropped on XML write
};
```

```csharp
// After (v7) — Code is no longer available on non-tooling measurements;
// the pre-v7 code was a latent bug (the value never reached the wire).
using MTConnect.Assets.CuttingTools.Measurements;

var diameter = new CuttingDiameterMeasurement
{
Value = 12.0m,
};
```

```csharp
// Tooling-measurement authors — Code stays available, but reads shift
// off the abstract base onto the concrete type.
using MTConnect.Assets.CuttingTools;

var tooling = new ToolingMeasurement
{
Value = 42.0m,
Code = "TM", // still available; declared directly on ToolingMeasurement in v7
};

// Reading — pre-v7 abstract-base read
Measurement m = tooling;
string c = ((ToolingMeasurement)m).Code; // cast to the concrete type
```

## See also

- [Assets — CuttingTool](/concepts/assets#cuttingtool) — the concept-level overview of the CuttingTool asset family, including the note that `Code` lives on `ToolingMeasurement` in v7.
- [`MTConnect.Assets.CuttingTools.Measurement`](/api/MTConnect.Assets.CuttingTools.Measurement) — the abstract base with `Code` now removed.
- [`MTConnect.Assets.CuttingTools.ToolingMeasurement`](/api/MTConnect.Assets.CuttingTools.ToolingMeasurement) — the concrete subclass that carries `Code` directly.
- [TrakHound/MTConnect.NET#224](https://github.com/TrakHound/MTConnect.NET/pull/224) — the PR that regenerated the CuttingTools `.g.cs` surface from v2.7 XMI and performed the relocation.
14 changes: 14 additions & 0 deletions docs/reference/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Every environment-variable reference discovered in the source tree. Both the C#

| Variable | Kinds | Default(s) |
| --- | --- | --- |
| `CI` | csharp-read | |
| `GITHUB_BASE_REF` | csharp-read | |
| `MTCONNECT_DOTNET_E2E_DIND` | powershell-read, shell-read | `0` |
| `MTCONNECT_DOTNET_IMAGE` | powershell-read, shell-read | `${IMAGE_DEFAULT}` |
| `MTCONNECT_DOTNET_SDK_TAG` | powershell-read, shell-read | `8.0` |
Expand All @@ -20,6 +22,18 @@ Every environment-variable reference discovered in the source tree. Both the C#

## Per-variable detail

### `CI`

| Kind | Source | Default / value | Context |
| --- | --- | --- | --- |
| `csharp-read` | [`tests/MTConnect.NET-SysML-Import-Tests/GeneratedCodeComplianceTests.cs:175`](https://github.com/TrakHound/MTConnect.NET/blob/master/tests/MTConnect.NET-SysML-Import-Tests/GeneratedCodeComplianceTests.cs#L175) | | = System.Environment.GetEnvironmentVariable("CI") |

### `GITHUB_BASE_REF`

| Kind | Source | Default / value | Context |
| --- | --- | --- | --- |
| `csharp-read` | [`tests/MTConnect.NET-SysML-Import-Tests/GeneratedCodeComplianceTests.cs:160`](https://github.com/TrakHound/MTConnect.NET/blob/master/tests/MTConnect.NET-SysML-Import-Tests/GeneratedCodeComplianceTests.cs#L160) | | = System.Environment.GetEnvironmentVariable("GITHUB_BASE_REF") |

### `MTCONNECT_DOTNET_E2E_DIND`

| Kind | Source | Default / value | Context |
Expand Down
2 changes: 1 addition & 1 deletion libraries/MTConnect.NET-Common/Assets/Asset.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,4 @@ public partial class Asset : IAsset
/// </summary>
public System.DateTime Timestamp { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@ public static class AssetDescriptions
/// </summary>
public const string Timestamp = "Time the Asset data was last modified.";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ public partial class ComponentConfigurationParametersAsset : Asset, IComponentCo
/// </summary>
public System.Collections.Generic.IEnumerable<MTConnect.Assets.ComponentConfigurationParameters.IParameterSet> ParameterSets { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ public static class ComponentConfigurationParametersAssetDescriptions
/// </summary>
public const string ParameterSets = "Set of Parameters.";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ public partial interface IComponentConfigurationParametersAsset : IAsset
/// </summary>
System.Collections.Generic.IEnumerable<MTConnect.Assets.ComponentConfigurationParameters.IParameterSet> ParameterSets { get; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ public interface IParameter
/// </summary>
string Value { get; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ public interface IParameterSet
/// </summary>
System.Collections.Generic.IEnumerable<MTConnect.Assets.ComponentConfigurationParameters.IParameter> Parameters { get; }
}
}
}
Loading