Skip to content
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 39 additions & 2 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,43 @@ on:
- 'docs/**'

jobs:
# ------------------------------------------------------------------
# Job 0 — dotnet format gate. Verifies the tree matches the
# repository's .editorconfig with zero diff, so formatting drift
# (indentation, brace placement, whitespace) is caught at PR time
# instead of silently accumulating into the baseline every
# subsequent branch then has to inherit. Uses the default "warn"
# severity — the same severity `dotnet format` applies with no
# --severity flag — rather than --severity info: at info severity
# dotnet format additionally tries to auto-fix long-standing Roslyn
# analyzer diagnostics (CA1859, CA1861, CA1018, ...) across the
# repo, which is a materially different (and, on this SDK/analyzer
# combination, occasionally crash-prone) undertaking from verifying
# whitespace/style formatting and is out of scope for this gate.
# Runs on the same draft-skip gate as the other jobs and does not
# depend on them, so a formatting-only fix gets fast feedback.
# ------------------------------------------------------------------
format:
name: format
if: github.event_name == 'push' || github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: Setup .NET 8.0 + 9.0
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4
with:
dotnet-version: |
8.0.x
9.0.x

- name: Restore solution
run: dotnet restore MTConnect.NET.sln

- name: Verify format (dotnet format --verify-no-changes)
run: dotnet format MTConnect.NET.sln --verify-no-changes --no-restore

# ------------------------------------------------------------------
# Job 1 — unsharded unit + integration sweep on both OS legs.
# Excludes Category=E2E altogether; the route walk is handled in
Expand All @@ -36,7 +73,7 @@ jobs:
# paid exactly once across the whole workflow (in job 2 below).
# ------------------------------------------------------------------
build-and-test:
name: build-and-test-${{ matrix.os }}
name: build-and-test
# Skip drafts: run only on push-to-master + ready (non-draft) PRs.
# The pull_request `types` list above includes `ready_for_review`
# so CI fires the moment a draft is flipped to ready.
Expand Down Expand Up @@ -323,7 +360,7 @@ jobs:
# categories run exactly once (in job 1) across the workflow.
# ------------------------------------------------------------------
route-check-e2e:
name: route-check-e2e-shard${{ matrix.shard }}of${{ matrix.shardTotal }}
name: route-check-e2e
if: github.event_name == 'push' || github.event.pull_request.draft == false
needs: docs-prepare
runs-on: ubuntu-latest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class AdapterConfigurationFileWatcher<TConfiguration> : ConfigurationFile
/// </summary>
/// <param name="path">Filesystem path to watch.</param>
/// <param name="interval">Poll interval in milliseconds.</param>
public AdapterConfigurationFileWatcher(string path, int interval = DefaultInterval) :base(path, interval) { }
public AdapterConfigurationFileWatcher(string path, int interval = DefaultInterval) : base(path, interval) { }


/// <summary>
Expand Down
6 changes: 5 additions & 1 deletion agent/MTConnect.NET-Agent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,11 @@ defaultVersion: 2.3

* `ignoreObservationCase` - Sets the default for Ignoring the case of Observation values. Applicable values will be converted to uppercase

* `inputValidationLevel` - Sets the default input validation level when new Observations are added to the Agent. 0 = Ignore, 1 = Warning, 2 = Strict
* `inputValidationLevel` - Sets the default per-DataItem validation level applied when new Observations and Assets are added to the Agent. Governs `InvalidObservationAdded` and `InvalidAssetAdded`. 0 = Ignore, 1 = Warning, 2 = Remove, 3 = Strict

* `deviceValidationLevel` - Sets the default device-shape validation level applied while a Device is being added or normalised (Component, Composition, DataItem). Independent from `inputValidationLevel` — a common integrator profile is `inputValidationLevel: Strict` alongside `deviceValidationLevel: Warning`. Governs `InvalidComponentAdded`, `InvalidCompositionAdded`, `InvalidDataItemAdded`, and `InvalidDeviceAdded`. 0 = Ignore, 1 = Warning, 2 = Remove, 3 = Strict

* `allowEmptyResultForEnumEvents` - When `true`, preserves an empty Result verbatim on VALUE-representation EVENT DataItems whose Type has a controlled vocabulary (`EXECUTION`, `CONTROLLER_MODE`, `AVAILABILITY`, etc.). Default `false` coerces the empty Result to `UNAVAILABLE`. Free-form String and Numeric-typed Events are unaffected.

* `monitorConfigurationFiles` - Sets whether Configuration files are monitored. If enabled and a configuration file is changed, the Agent will restart

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class AgentConfigurationFileWatcher<TConfiguration> : ConfigurationFileWa
/// </summary>
/// <param name="path">Filesystem path to watch.</param>
/// <param name="interval">Poll interval in milliseconds.</param>
public AgentConfigurationFileWatcher(string path, int interval = DefaultInterval) :base(path, interval) { }
public AgentConfigurationFileWatcher(string path, int interval = DefaultInterval) : base(path, interval) { }


/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ public void StartAgent(IAgentApplicationConfiguration configuration, bool verbos
_agentLogger.Warn($"No Devices Found : Reading from : {configuration.Devices}");
}
}


// Initilialize Processors
_processors = new MTConnectAgentProcessors(configuration);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ private Stream ReadRequestBody(Stream inputStream)
var outputBytes = Encoding.Convert(Encoding.ASCII, Encoding.UTF8, inputBytes);
return new MemoryStream(outputBytes);
}

}
catch { }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -959,7 +959,7 @@ await AsyncVoidGuard.Run(
{
multipleObservations.Add(CloneAsObservation(conditionObservation));
}

var result = await _entityServer.PublishObservations(_mqttClient, multipleObservations);
if (result != null && result.IsSuccess)
{
Expand Down
38 changes: 19 additions & 19 deletions agent/Modules/MTConnect.NET-AgentModule-ShdrAdapter/Module.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,13 @@ private void AddAdapter(IShdrAdapterClientConfiguration configuration, IDevice d

if (configuration.OutputConnectionInformation)
{
// Initialize Adapter URI Observation
var adapterUriDataItem = adapterComponent.GetDataItemByType(AdapterUriDataItem.TypeId);
if (adapterUriDataItem != null && initializeDataItems)
{
_mtconnectAgent.AddObservation(adapterUriDataItem, adapterComponent.Uri);
}
}
// Initialize Adapter URI Observation
var adapterUriDataItem = adapterComponent.GetDataItemByType(AdapterUriDataItem.TypeId);
if (adapterUriDataItem != null && initializeDataItems)
{
_mtconnectAgent.AddObservation(adapterUriDataItem, adapterComponent.Uri);
}
}

// Create new SHDR Adapter Client to read from SHDR stream
var adapterClient = new ShdrAdapterClient(configuration, _mtconnectAgent, device, idSuffix);
Expand All @@ -160,9 +160,9 @@ private void AddAdapter(IShdrAdapterClientConfiguration configuration, IDevice d
_mtconnectAgent.AddObservation(connectionStatusDataItem, ConnectionStatus.LISTEN);
}

// Start the Adapter Client
adapterClient.Start();
}
// Start the Adapter Client
adapterClient.Start();
}
}


Expand All @@ -181,8 +181,8 @@ private void AdapterConnected(object sender, string message)
if (_configuration.AvailableOnConnection)
{
var availabilityDataItem = adapterClient.Device.GetDataItemByType(AvailabilityDataItem.TypeId);
_mtconnectAgent.AddObservation(availabilityDataItem, Availability.AVAILABLE);
}
_mtconnectAgent.AddObservation(availabilityDataItem, Availability.AVAILABLE);
}

Log(MTConnectLogLevel.Information, $"ID = " + adapterClient.Id + " : " + message);
}
Expand All @@ -198,14 +198,14 @@ private void AdapterDisconnected(object sender, string message)
_mtconnectAgent.AddObservation(connectionStatusDataItem, ConnectionStatus.CLOSED);
}

// Set Availability (if AvailableOnConnection = TRUE)
if (_configuration.AvailableOnConnection)
{
var availabilityDataItem = adapterClient.Device.GetDataItemByType(AvailabilityDataItem.TypeId);
_mtconnectAgent.AddObservation(availabilityDataItem, Availability.UNAVAILABLE);
}
// Set Availability (if AvailableOnConnection = TRUE)
if (_configuration.AvailableOnConnection)
{
var availabilityDataItem = adapterClient.Device.GetDataItemByType(AvailabilityDataItem.TypeId);
_mtconnectAgent.AddObservation(availabilityDataItem, Availability.UNAVAILABLE);
}

Log(MTConnectLogLevel.Information, $"ID = " + adapterClient.Id + " : " + message);
Log(MTConnectLogLevel.Information, $"ID = " + adapterClient.Id + " : " + message);
}

private void AdapterConnectionError(object sender, Exception exception)
Expand Down
18 changes: 9 additions & 9 deletions build/MTConnect.NET-DocsGen/RouteInventory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,8 @@ private static (string? method, string? handler) SniffLambdaGate(ParenthesizedLa
// the *summary text* still flows from /// on the handler class.
private static readonly IReadOnlyDictionary<string, IReadOnlyList<EndpointParam>> CeenHandlerParameters
= new Dictionary<string, IReadOnlyList<EndpointParam>>
{
["MTConnectProbeResponseHandler"] = new EndpointParam[]
{
["MTConnectProbeResponseHandler"] = new EndpointParam[]
{
new("deviceType", "Query", "string", null, "Optional device-type filter."),
new("version", "Query", "string", null, "Target MTConnect Standard version of the response document."),
Expand All @@ -230,7 +230,7 @@ private static readonly IReadOnlyDictionary<string, IReadOnlyList<EndpointParam>
new("indentOutput", "Query", "bool", null, "Pretty-print the response document."),
new("outputComments", "Query", "bool", null, "Emit comments / annotations in the response document."),
},
["MTConnectCurrentResponseHandler"] = new EndpointParam[]
["MTConnectCurrentResponseHandler"] = new EndpointParam[]
{
new("path", "Query", "string", null, "XPath that filters the data items included in the response."),
new("at", "Query", "ulong", null, "Sequence number anchoring the snapshot."),
Expand All @@ -242,7 +242,7 @@ private static readonly IReadOnlyDictionary<string, IReadOnlyList<EndpointParam>
new("indentOutput", "Query", "bool", null, "Pretty-print the response document."),
new("outputComments", "Query", "bool", null, "Emit comments / annotations in the response document."),
},
["MTConnectSampleResponseHandler"] = new EndpointParam[]
["MTConnectSampleResponseHandler"] = new EndpointParam[]
{
new("path", "Query", "string", null, "XPath that filters the data items included in the response."),
new("from", "Query", "ulong", null, "Sequence number lower bound."),
Expand All @@ -256,28 +256,28 @@ private static readonly IReadOnlyDictionary<string, IReadOnlyList<EndpointParam>
new("indentOutput", "Query", "bool", null, "Pretty-print the response document."),
new("outputComments", "Query", "bool", null, "Emit comments / annotations in the response document."),
},
["MTConnectAssetsResponseHandler"] = new EndpointParam[]
["MTConnectAssetsResponseHandler"] = new EndpointParam[]
{
new("type", "Query", "string", null, "Asset type filter (e.g. CuttingTool)."),
new("removed", "Query", "bool", null, "Include removed assets when true."),
new("count", "Query", "int", null, "Maximum number of assets."),
new("documentFormat", "Query", "string", "xml", "Response document format."),
new("indentOutput", "Query", "bool", null, "Pretty-print the response document."),
},
["MTConnectAssetResponseHandler"] = new EndpointParam[]
["MTConnectAssetResponseHandler"] = new EndpointParam[]
{
new("assetId", "Route", "string", null, "Asset identifier captured from the trailing path segment."),
new("documentFormat", "Query", "string", "xml", "Response document format."),
},
["MTConnectPutResponseHandler"] = new EndpointParam[]
["MTConnectPutResponseHandler"] = new EndpointParam[]
{
new("(form / query)", "Body", "Dictionary<string,string>", null, "DataItemId=Value entries to enqueue as observations."),
},
["MTConnectPostResponseHandler"] = new EndpointParam[]
["MTConnectPostResponseHandler"] = new EndpointParam[]
{
new("(body)", "Body", "string", null, "Asset document payload."),
},
};
};

// Cache of parsed /// summary text per handler-class file path, so
// we only Roslyn-parse each file once even though several variables
Expand Down
4 changes: 2 additions & 2 deletions build/MTConnect.NET-SysML-Import/CSharp/ClassModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public static ClassModel Create(MTConnectClassModel importModel)
{
var propertyValue = importProperty.GetValue(importModel);

var exportProperty = exportProperties.FirstOrDefault(o => o.Name == importProperty.Name);
var exportProperty = exportProperties.FirstOrDefault(o => o.Name == importProperty.Name);
if (exportProperty != null && exportProperty.PropertyType == importProperty.PropertyType)
{
exportProperty.SetValue(exportModel, propertyValue);
Expand All @@ -62,7 +62,7 @@ public static ClassModel Create(MTConnectClassModel importModel)

// Remove 'Enum' suffix
if (exportPropertyModel.DataType.EndsWith("Enum"))
{
{
var suffix = "Enum";
if (exportPropertyModel.DataType.EndsWith(suffix)) exportPropertyModel.DataType = exportPropertyModel.DataType.Substring(0, exportPropertyModel.DataType.Length - suffix.Length);
}
Expand Down
2 changes: 1 addition & 1 deletion build/MTConnect.NET-SysML-Import/CSharp/ComponentType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public ComponentType() { }
/// <param name="idPrefix">Identifier prefix applied to the
/// rendered type.</param>
/// <param name="umlClass">Backing UML class.</param>
public ComponentType(XmiDocument xmiDocument, string idPrefix, UmlClass umlClass) : base (xmiDocument, idPrefix, umlClass) { }
public ComponentType(XmiDocument xmiDocument, string idPrefix, UmlClass umlClass) : base(xmiDocument, idPrefix, umlClass) { }


/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion build/MTConnect.NET-SysML-Import/CSharp/CompositionType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public CompositionType() { }
/// rendered type.</param>
/// <param name="umlEnumerationLiteral">Backing UML enumeration
/// literal.</param>
public CompositionType(XmiDocument xmiDocument, string idPrefix, UmlEnumerationLiteral umlEnumerationLiteral) : base (xmiDocument, idPrefix, umlEnumerationLiteral) { }
public CompositionType(XmiDocument xmiDocument, string idPrefix, UmlEnumerationLiteral umlEnumerationLiteral) : base(xmiDocument, idPrefix, umlEnumerationLiteral) { }


/// <summary>
Expand Down
32 changes: 16 additions & 16 deletions build/MTConnect.NET-SysML-Import/CSharp/DataItemType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public DataItemType() { }
/// <param name="subClasses">Optional sub-classes that derive
/// from <paramref name="umlClass"/>.</param>
public DataItemType(XmiDocument xmiDocument, string category, string idPrefix, UmlClass umlClass, UmlEnumerationLiteral umlEnumerationLiteral, IEnumerable<UmlClass> subClasses = null)
: base (xmiDocument, category, idPrefix, umlClass, umlEnumerationLiteral, subClasses) { }
: base(xmiDocument, category, idPrefix, umlClass, umlEnumerationLiteral, subClasses) { }


/// <summary>
Expand Down Expand Up @@ -155,19 +155,19 @@ public virtual string RenderModel()
public string RenderDescriptions() => null;


private static string GetName(string type)
{
switch (type)
{
case "EMERGENCY_STOP": return "estop";
case "CONTROLLER_MODE": return "mode";
case "EXECUTION": return "exec";
case "LOAD": return "load";
case "POSITION": return "pos";
case "TEMPERATURE": return "temp";
}

return type.ToCamelCase();
}
}
private static string GetName(string type)
{
switch (type)
{
case "EMERGENCY_STOP": return "estop";
case "CONTROLLER_MODE": return "mode";
case "EXECUTION": return "exec";
case "LOAD": return "load";
case "POSITION": return "pos";
case "TEMPERATURE": return "temp";
}

return type.ToCamelCase();
}
}
}
2 changes: 1 addition & 1 deletion build/MTConnect.NET-SysML-Import/CSharp/EnumModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public static EnumModel Create(MTConnectEnumModel importModel, Func<string, stri
{
var propertyValue = importProperty.GetValue(importModel);

var exportProperty = exportProperties.FirstOrDefault(o => o.Name == importProperty.Name);
var exportProperty = exportProperties.FirstOrDefault(o => o.Name == importProperty.Name);
if (exportProperty != null && exportProperty.PropertyType == importProperty.PropertyType)
{
exportProperty.SetValue(exportModel, propertyValue);
Expand Down
2 changes: 1 addition & 1 deletion build/MTConnect.NET-SysML-Import/CSharp/EnumStringModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public static EnumStringModel Create(MTConnectEnumModel importModel, Func<string
{
var propertyValue = importProperty.GetValue(importModel);

var exportProperty = exportProperties.FirstOrDefault(o => o.Name == importProperty.Name);
var exportProperty = exportProperties.FirstOrDefault(o => o.Name == importProperty.Name);
if (exportProperty != null && exportProperty.PropertyType == importProperty.PropertyType)
{
exportProperty.SetValue(exportModel, propertyValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public InterfaceDataItemType() { }
/// literal.</param>
/// <param name="subClasses">Optional sub-classes.</param>
public InterfaceDataItemType(XmiDocument xmiDocument, string category, string idPrefix, UmlClass umlClass, UmlEnumerationLiteral umlEnumerationLiteral, IEnumerable<UmlClass> subClasses = null)
: base (xmiDocument, category, idPrefix, umlClass, umlEnumerationLiteral, subClasses) { }
: base(xmiDocument, category, idPrefix, umlClass, umlEnumerationLiteral, subClasses) { }


/// <summary>
Expand Down
Loading
Loading