From bc7cd3fcaacf86cb9e632081094153fcf6f29a24 Mon Sep 17 00:00:00 2001 From: Peter Kurhajec <61538034+PTKu@users.noreply.github.com> Date: Wed, 25 Feb 2026 12:44:03 +0100 Subject: [PATCH 01/13] Update AXSharp package versions to 0.47.0-alpha.452 --- .config/dotnet-tools.json | 6 +++--- Directory.Packages.props | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 4f7f693ff..5d4f7c956 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "AXSharp.ixc": { - "version": "0.47.0-alpha.439", + "version": "0.47.0-alpha.452", "commands": [ "ixc" ], @@ -17,14 +17,14 @@ "rollForward": false }, "AXSharp.ixd": { - "version": "0.47.0-alpha.439", + "version": "0.47.0-alpha.452", "commands": [ "ixd" ], "rollForward": false }, "AXSharp.ixr": { - "version": "0.47.0-alpha.439", + "version": "0.47.0-alpha.452", "commands": [ "ixr" ], diff --git a/Directory.Packages.props b/Directory.Packages.props index 35a9fb605..27a94aace 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,11 +11,11 @@ - - - - - + + + + + From 2759378606bed4c4ce7493ae262b8a70ff1b7f82 Mon Sep 17 00:00:00 2001 From: Peter Kurhajec <61538034+PTKu@users.noreply.github.com> Date: Wed, 25 Feb 2026 13:27:44 +0100 Subject: [PATCH 02/13] adjustments to the logger to provide start-end entry --- .../ctrl/src/AxoLogger/IAxoLogger.st | 7 +- src/core/ctrl/src/AxoLogger/AxoLogEntry.st | 6 ++ src/core/ctrl/src/AxoLogger/AxoLogger.st | 6 +- .../src/AxoMessaging/Static/AxoMessenger.st | 30 ++++--- src/core/ctrl/src/abstractions/NULLs.st | 1 + .../src/AXOpen.Core/AxoLogger/AxoLogger.cs | 4 +- .../AxoMessenger/Static/AxoMessenger.cs | 19 +++-- src/traversals/apax/apax.yml | 81 +++++++++++++++++++ 8 files changed, 130 insertions(+), 24 deletions(-) create mode 100644 src/traversals/apax/apax.yml diff --git a/src/abstractions/ctrl/src/AxoLogger/IAxoLogger.st b/src/abstractions/ctrl/src/AxoLogger/IAxoLogger.st index 17a5aa0ef..5f132d4ad 100644 --- a/src/abstractions/ctrl/src/AxoLogger/IAxoLogger.st +++ b/src/abstractions/ctrl/src/AxoLogger/IAxoLogger.st @@ -25,7 +25,7 @@ NAMESPACE AXOpen.Logging /// _message is a string of maximum 80 characters that represents the log message /// _message : STRING[80]; - + /// /// _level is an instance of eLogLevel that represents the level of the log /// @@ -35,6 +35,11 @@ NAMESPACE AXOpen.Logging /// _sender is an instance of IAxoObject that represents the sender of the log /// _sender : IAxoObject; + + /// + /// _messageCode is an unsigned long integer that represents the code of the log message + /// + _messageCode : ULINT; END_VAR END_METHOD diff --git a/src/core/ctrl/src/AxoLogger/AxoLogEntry.st b/src/core/ctrl/src/AxoLogger/AxoLogEntry.st index 0c58d7e90..48c2c6df4 100644 --- a/src/core/ctrl/src/AxoLogger/AxoLogEntry.st +++ b/src/core/ctrl/src/AxoLogger/AxoLogEntry.st @@ -10,6 +10,12 @@ NAMESPACE AXOpen.Logging /// Message : STRING[80]; + + /// + /// Message code. The code will provide information about the text of the message from message tables of respective messenger. + /// + MessageCode : ULINT; + /// /// The severity level of the log entry. /// diff --git a/src/core/ctrl/src/AxoLogger/AxoLogger.st b/src/core/ctrl/src/AxoLogger/AxoLogger.st index 9b3e5a283..c4b6752db 100644 --- a/src/core/ctrl/src/AxoLogger/AxoLogger.st +++ b/src/core/ctrl/src/AxoLogger/AxoLogger.st @@ -31,11 +31,13 @@ NAMESPACE AXOpen.Logging /// The message to be logged. /// The severity level of the log. /// The object that sends the log. + /// The code of the log message. METHOD PUBLIC Log VAR_INPUT _message : STRING[80]; _level : eLogLevel; - _sender : IAxoObject; + _sender : IAxoObject; + _messageCode : ULINT; END_VAR IF(_level >= THIS.MinimumLevel) THEN @@ -45,6 +47,7 @@ NAMESPACE AXOpen.Logging LogEntries[Carret].Message := _message; LogEntries[Carret].Level := _level; + LogEntries[Carret].MessageCode := _messageCode; IF(_sender <> NULL) THEN LogEntries[Carret].Sender := _sender.GetIdentity(); @@ -75,6 +78,7 @@ NAMESPACE AXOpen.Logging LogEntries[Carret].Level := _level; LogEntries[Carret].ToDequeue := TRUE; LogEntries[Carret].Sender := ULINT#0; + LogEntries[Carret].MessageCode := ULINT#0; Carret := Carret + 1; END_IF; END_METHOD diff --git a/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st b/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st index 786e8eed7..c0b64cce4 100644 --- a/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st +++ b/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st @@ -58,13 +58,15 @@ NAMESPACE AXOpen.Messaging.Static THIS.MessengerState := eAxoMessengerState#ActiveAcknowledgeRequired; END_IF; - IF THIS.MessengerState = eAxoMessengerState#ActiveAcknowledgeRequired OR THIS.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired OR THIS.MessengerState = eAxoMessengerState#ActiveAlreadyAcknowledged THEN + IF THIS.MessengerState = eAxoMessengerState#ActiveAcknowledgeRequired OR + THIS.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired OR + THIS.MessengerState = eAxoMessengerState#ActiveAlreadyAcknowledged THEN IF _context.OpenCycleCount() = ULINT#0 OR _context.GetRtc().NowUTC() = LDATE_AND_TIME#1970-01-01-00:00:00.000 THEN THIS.MessengerState := eAxoMessengerState#InvalidImplementation; THIS.Category := eAxoMessageCategory#ProgrammingError; END_IF; IF _context.OpenCycleCount() - ActiveContextCount > UINT#1 THEN - THIS.Deactivate(MessageCode); + THIS.Deactivate(MessageCode, THIS.ToLogLevel(Category)); END_IF; END_IF; @@ -114,18 +116,19 @@ NAMESPACE AXOpen.Messaging.Static Risen := _context.GetRtc().NowUTC(); Fallen := LDATE_AND_TIME#1970-01-01-00:00:00.000; Acknowledged := LDATE_AND_TIME#1970-01-01-00:00:00.000; - _context.GetLogger().Log('<#Risen#>', THIS.ToLogLevel(_category), THIS); + _context.GetLogger().Log('$5E', THIS.ToLogLevel(_category), THIS, _messageCode); MessageCode := _messageCode; Category := _category; // AcknowledgementRequired := Category >= eAxoMessageCategory#Error; END_IF; // "Reactivation" in case of acknowledgable alarm rised, falled and rised again without acknowledgement - IF THIS.MessengerState = eAxoMessengerState#InactiveWaitingForAcknowledge AND MessageCode = _messageCode AND ActiveContextCount = ULINT#0 THEN + IF THIS.MessengerState = eAxoMessengerState#InactiveWaitingForAcknowledge AND + MessageCode = _messageCode AND + ActiveContextCount = ULINT#0 THEN Risen := _context.GetRtc().NowUTC(); Fallen := LDATE_AND_TIME#1970-01-01-00:00:00.000; - Acknowledged := LDATE_AND_TIME#1970-01-01-00:00:00.000; - _context.GetLogger().Log('<#Risen again before acknowledgement#>', THIS.ToLogLevel(_category), THIS); + Acknowledged := LDATE_AND_TIME#1970-01-01-00:00:00.000; END_IF; IF MessageCode = _messageCode THEN @@ -161,7 +164,7 @@ NAMESPACE AXOpen.Messaging.Static IF _condition THEN ActivateOnCondition := THIS.Activate(_messageCode,_category); ELSE - THIS.Deactivate(_messageCode); + THIS.Deactivate(_messageCode, THIS.ToLogLevel(_category)); END_IF; END_METHOD @@ -187,6 +190,7 @@ NAMESPACE AXOpen.Messaging.Static METHOD PRIVATE Deactivate VAR_INPUT _messageCode : ULINT; + _logLevel : eLogLevel; END_VAR IF _context = NULL THEN _context := THIS.GetContext(); @@ -195,16 +199,18 @@ NAMESPACE AXOpen.Messaging.Static IF _context = NULL THEN RETURN; END_IF; - + IF _messageCode = ULINT#0 THEN RETURN; END_IF; - - IF THIS.MessengerState = eAxoMessengerState#ActiveAcknowledgeRequired OR THIS.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired OR THIS.MessengerState = eAxoMessengerState#ActiveAlreadyAcknowledged THEN + + IF THIS.MessengerState = eAxoMessengerState#ActiveAcknowledgeRequired OR + THIS.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired OR + THIS.MessengerState = eAxoMessengerState#ActiveAlreadyAcknowledged THEN IF MessageCode = _messageCode THEN ActiveContextCount := ULINT#0; - Fallen := _context.GetRtc().NowUTC(); - _context.GetLogger().Log('<#Fallen#>', eLogLevel#Information, THIS); + Fallen := _context.GetRtc().NowUTC(); + _context.GetLogger().Log('$76', _logLevel, THIS, _messageCode); IF THIS.MessengerState = eAxoMessengerState#ActiveAcknowledgeRequired THEN THIS.MessengerState := eAxoMessengerState#InactiveWaitingForAcknowledge; ELSIF THIS.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired THEN diff --git a/src/core/ctrl/src/abstractions/NULLs.st b/src/core/ctrl/src/abstractions/NULLs.st index a335d74b3..e5422295f 100644 --- a/src/core/ctrl/src/abstractions/NULLs.st +++ b/src/core/ctrl/src/abstractions/NULLs.st @@ -122,6 +122,7 @@ NAMESPACE AXOpen.Core _message : STRING[80]; _level : eLogLevel; _sender : IAxoObject; + _messageCode : ULINT; END_VAR ; END_METHOD diff --git a/src/core/src/AXOpen.Core/AxoLogger/AxoLogger.cs b/src/core/src/AXOpen.Core/AxoLogger/AxoLogger.cs index 03aa3256b..c1222a077 100644 --- a/src/core/src/AXOpen.Core/AxoLogger/AxoLogger.cs +++ b/src/core/src/AXOpen.Core/AxoLogger/AxoLogger.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Security.Principal; @@ -60,7 +60,7 @@ await Task.Run(async () => { case AxoMessenger messenger: await messenger.ReadAsync(); - message = $"{entry.Message.LastValue} : {messenger.GetMessageText()}"; + message = $"{entry.Message.LastValue} : {messenger.GetMessageText(entry.MessageCode.LastValue)}"; break; case AxoStep step: await step.ReadAsync(); diff --git a/src/core/src/AXOpen.Core/AxoMessenger/Static/AxoMessenger.cs b/src/core/src/AXOpen.Core/AxoMessenger/Static/AxoMessenger.cs index cf9687b90..06537dd6e 100644 --- a/src/core/src/AXOpen.Core/AxoMessenger/Static/AxoMessenger.cs +++ b/src/core/src/AXOpen.Core/AxoMessenger/Static/AxoMessenger.cs @@ -197,21 +197,24 @@ public async Task ReadDetailsAsync() return FindParentOfType(node.GetParent(), depth++); } + + public string GetMessageText() + { + return GetMessageText(this.MessageCode.LastValue); + } + /// /// Retrieves the message text based on the message code. /// /// The message text string. - public string GetMessageText() - { + public string GetMessageText(ulong messageCode) + { //18446744073709551615 - - ulong messageCode = this.MessageCode.LastValue; - if (messageCode == ulong.MaxValue) - { + { return this.Message.LastValue; } - + string retVal = ""; string prefix = ""; if (this.MessengerState.Equals(eAxoMessengerState.InvalidImplementation) || this.MessengerState.LastValue.Equals((short)eAxoMessengerState.InvalidImplementation)) @@ -345,4 +348,4 @@ private void ChekIfHelpTextDefined() public class EmptyMessenger { public string MessageText { get; set; } = "All good here."; -} \ No newline at end of file +} diff --git a/src/traversals/apax/apax.yml b/src/traversals/apax/apax.yml new file mode 100644 index 000000000..35d99764d --- /dev/null +++ b/src/traversals/apax/apax.yml @@ -0,0 +1,81 @@ +name: "apax.traversal" +version: "0.0.0-dev.0" +type: "app" +targets: +- "1500" +registries: + '@inxton': "https://npm.pkg.github.com/" +devDependencies: + '@inxton/ax-sdk': "0.0.0-dev.0" +dependencies: + "abstractions-app": "0.0.0-dev.0" + "@inxton/axopen.abstractions": "0.0.0-dev.0" + "@inxton/ax.axopen.app": "0.0.0-dev.0" + "@inxton/ax.axopen.hwlibrary": "0.0.0-dev.0" + "@inxton/ax.axopen.min": "0.0.0-dev.0" + "@inxton/ax.catalog": "0.0.46" + "app_axopen.components.abb.robotics": "0.0.0-dev.0" + "@inxton/axopen.components.abb.robotics": "0.0.0-dev.0" + "components.abstractions-app": "0.0.0-dev.0" + "@inxton/axopen.components.abstractions": "0.0.0-dev.0" + "app_axopen.components.balluff.identification": "0.0.0-dev.0" + "@inxton/axopen.components.balluff.identification": "0.0.0-dev.0" + "app_axopen.components.cognex.vision": "0.0.0-dev.0" + "@inxton/axopen.components.cognex.vision": "0.0.0-dev.0" + "app_axopen.components.desoutter.tightening": "0.0.0-dev.0" + "@inxton/axopen.components.desoutter.tightening": "0.0.0-dev.0" + "app_axopen.components.drives": "0.0.0-dev.0" + "@inxton/axopen.components.drives": "0.0.0-dev.0" + "app_axopen.components.dukane.welders": "0.0.0-dev.0" + "@inxton/axopen.components.dukane.welders": "0.0.0-dev.0" + "elementscomponents": "0.0.0-dev.0" + "@inxton/axopen.components.elements": "0.0.0-dev.0" + "app_axopen.components.festo.drives": "0.0.0-dev.0" + "@inxton/axopen.components.festo.drives": "0.0.0-dev.0" + "app_axopen.components.keyence.vision": "0.0.0-dev.0" + "@inxton/axopen.components.keyence.vision": "0.0.0-dev.0" + "app_axopen.components.kuka.robotics": "0.0.0-dev.0" + "@inxton/axopen.components.kuka.robotics": "0.0.0-dev.0" + "app_axopen.components.mitsubishi.robotics": "0.0.0-dev.0" + "@inxton/axopen.components.mitsubishi.robotics": "0.0.0-dev.0" + "pneumaticcomponents": "0.0.0-dev.0" + "@inxton/axopen.components.pneumatics": "0.0.0-dev.0" + "app_axopen.components.rexroth.drives": "0.0.0-dev.0" + "@inxton/axopen.components.rexroth.drives": "0.0.0-dev.0" + "app_axopen.components.rexroth.press": "0.0.0-dev.0" + "@inxton/axopen.components.rexroth.press": "0.0.0-dev.0" + "app_axopen.components.rexroth.tightening": "0.0.0-dev.0" + "@inxton/axopen.components.rexroth.tightening": "0.0.0-dev.0" + "app_axopen.components.robotics": "0.0.0-dev.0" + "@inxton/axopen.components.robotics": "0.0.0-dev.0" + "app_axopen.components.siem.communication": "0.0.0-dev.0" + "@inxton/axopen.components.siem.communication": "0.0.0-dev.0" + "app_axopen.components.siem.identification": "0.0.0-dev.0" + "@inxton/axopen.components.siem.identification": "0.0.0-dev.0" + "app_axopen.components.ur.robotics": "0.0.0-dev.0" + "@inxton/axopen.components.ur.robotics": "0.0.0-dev.0" + "app_axopen.components.zebra.vision": "0.0.0-dev.0" + "@inxton/axopen.components.zebra.vision": "0.0.0-dev.0" + "ix_axopencore": "0.0.0-dev.0" + "@inxton/axopen.core": "0.0.0-dev.0" + "axopen.data-app": "0.0.0-dev.0" + "@inxton/axopen.data": "0.0.0-dev.0" + "axopen.data.tests_l1": "0.0.0-dev.0" + "axopen.integration.tests_l4": "0.0.0-dev.0" + "axopen.inspectors": "0.0.0-dev.0" + "@inxton/axopen.inspectors": "0.0.0-dev.0" + "axopen.integrations": "0.0.0-dev.0" + "app_axopen.io": "0.0.0-dev.0" + "@inxton/axopen.io": "0.0.0-dev.0" + "probers-app": "0.0.0-dev.0" + "@inxton/axopen.probers": "0.0.0-dev.0" + "simatic1500-app": "0.0.0-dev.0" + "@inxton/axopen.simatic1500": "0.0.0-dev.0" + "app_apaxappname": "0.0.0-dev.0" + "@inxton/apaxlibname": "0.0.0-dev.0" + "timers-app": "0.0.0-dev.0" + "@inxton/axopen.timers": "0.0.0-dev.0" + "utils-app": "0.0.0-dev.0" + "@inxton/axopen.utils": "0.0.0-dev.0" +installStrategy: "overridable" +... From 3ba4c1c7a1e7c37341e1ff910fffb00124ac14fe Mon Sep 17 00:00:00 2001 From: Peter Kurhajec <61538034+PTKu@users.noreply.github.com> Date: Mon, 2 Mar 2026 14:48:38 +0100 Subject: [PATCH 03/13] Refactor logger messages to use InspectorDescription method for consistency --- .../AxoInspectorDialogDialogView.razor | 8 ++++++-- .../AxoInspectorDialogDialogView.razor.cs | 13 +++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/inspectors/src/AxOpen.Inspectors.Blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor b/src/inspectors/src/AxOpen.Inspectors.Blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor index ac31b4da5..629d0838d 100644 --- a/src/inspectors/src/AxOpen.Inspectors.Blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor +++ b/src/inspectors/src/AxOpen.Inspectors.Blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor @@ -1,4 +1,4 @@ -@namespace AXOpen.Inspectors +@namespace AXOpen.Inspectors @using System.Globalization @using AXOpen.Core.Blazor.AxoDialogs @using AXSharp.Connector.Localizations @@ -57,10 +57,13 @@ @code { + private string? currentUrl; string InspectionDescription { get; set; } + string InspectionId { get; set; } + eInspectorType InspectorType { get; set; } async Task GetInspectorType() @@ -72,8 +75,9 @@ { currentUrl = NavigationManager.ToBaseRelativePath(NavigationManager.Uri); NavigationManager.LocationChanged += OnLocationChanged; - + InspectionDescription = await Component._inspectionDetails.GetAsync(CultureInfo.CurrentCulture); + InspectionId = Component._inspectionDetails.LastValue; InspectorType = await GetInspectorType(); return base.OnInitializedAsync(); } diff --git a/src/inspectors/src/AxOpen.Inspectors.Blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor.cs b/src/inspectors/src/AxOpen.Inspectors.Blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor.cs index 35658b9b5..a4d42796d 100644 --- a/src/inspectors/src/AxOpen.Inspectors.Blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor.cs +++ b/src/inspectors/src/AxOpen.Inspectors.Blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor.cs @@ -1,4 +1,4 @@ -using AXOpen.Core; +using AXOpen.Core; using AXOpen.Core.Blazor.AxoDialogs; using AXOpen.Logging; using AXSharp.Connector; @@ -17,6 +17,11 @@ namespace AXOpen.Inspectors public partial class AxoInspectorDialogDialogView : AxoDialogBaseView, IDisposable { + private string? InspectorDescription() + { + return InspectionId; + } + public bool RetryDisabled { get; set; } = false; protected override void OnAfterRender(bool firstRender) @@ -56,7 +61,7 @@ public async Task Retry() base.Component._dialogueRetry.Edit = true; await base.CloseDialogsWithSignalR(); var identity = (await _asp.GetAuthenticationStateAsync()).User.Identity; - AxoApplication.Current.Logger.Information($"{nameof(Retry)} of '{Component.HumanReadable}' was executed.", identity); + AxoApplication.Current.Logger.Information($"{nameof(Retry)} of '{InspectorDescription()}' was executed.", identity); } else { @@ -69,14 +74,14 @@ public async Task Terminate() base.Component._dialogueTerminate.Edit = true; await base.CloseDialogsWithSignalR(); var identity = (await _asp.GetAuthenticationStateAsync()).User.Identity; - AxoApplication.Current.Logger.Information($"{nameof(Terminate)} of '{Component.HumanReadable}' was executed.", identity); + AxoApplication.Current.Logger.Information($"{nameof(Terminate)} of '{InspectorDescription()}' was executed.", identity); } public async Task Override() { base.Component._dialogueOverride.Edit = true; await base.CloseDialogsWithSignalR(); var identity = (await _asp.GetAuthenticationStateAsync()).User.Identity; - AxoApplication.Current.Logger.Information($"{nameof(Override)} of '{Component.HumanReadable}' was executed.", identity); + AxoApplication.Current.Logger.Information($"{nameof(Override)} of '{InspectorDescription()}' was executed.", identity); } From 25ede38107364e34f945b4003c5d5b15c62be237 Mon Sep 17 00:00:00 2001 From: Peter Kurhajec <61538034+PTKu@users.noreply.github.com> Date: Mon, 2 Mar 2026 14:50:16 +0100 Subject: [PATCH 04/13] Refactor logging and enhance inspector dialog details Changed dialog event logging from Information to Verbose for reduced log noise. Added relevant using directives for dialogs, localization, and authentication. Inspector dialog now tracks current URL and retrieves inspection details/ID asynchronously. Log messages for inspector actions now use InspectionId for better traceability. Minor formatting and code structure improvements. --- .../AxoDialogs/Locator/AxoDialogLocator.razor.cs | 10 +++++----- .../AxoDialogs/Locator/AxoDialogLocatorService.cs | 10 +++++----- .../AxoInspectorDialogDialogView.razor | 8 ++++++-- .../AxoInspectorDialogDialogView.razor.cs | 13 +++++++++---- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/core/src/AXOpen.Core.Blazor/AxoDialogs/Locator/AxoDialogLocator.razor.cs b/src/core/src/AXOpen.Core.Blazor/AxoDialogs/Locator/AxoDialogLocator.razor.cs index cab3c9ac2..11e46e7b0 100644 --- a/src/core/src/AXOpen.Core.Blazor/AxoDialogs/Locator/AxoDialogLocator.razor.cs +++ b/src/core/src/AXOpen.Core.Blazor/AxoDialogs/Locator/AxoDialogLocator.razor.cs @@ -1,4 +1,4 @@ -using AXOpen.Core.Blazor.AxoDialogs.Hubs; +using AXOpen.Core.Blazor.AxoDialogs.Hubs; using AXOpen.Core.Blazor.Dialogs; using AXSharp.Connector; using Microsoft.AspNetCore.Components; @@ -88,27 +88,27 @@ protected override async Task InitializeObservationHandling() private async void OnSignalRClient_DialogOpen(object sender, SignalRClientReceivedMessageArgs e) { - Log.Logger.Information($"AxoDialogLocator by SignalR Opening : {e.SymbolOfDialogInstance}"); + Log.Logger.Verbose($"AxoDialogLocator by SignalR Opening : {e.SymbolOfDialogInstance}"); // this message is no supported and required at this moment. await Refresh(); } private async void OnSignalRClient_DialogClose(object sender, SignalRClientReceivedMessageArgs e) { - Log.Logger.Information($"AxoDialogLocator by SignalR Closing: {e.SymbolOfDialogInstance}"); + Log.Logger.Verbose($"AxoDialogLocator by SignalR Closing: {e.SymbolOfDialogInstance}"); _dialogProxyService.RemoveDisplayedDialog(e.SymbolOfDialogInstance); await Refresh(); } private async void OnPlc_DialogInvoked(object? sender, AxoDialogEventArgs e) { - Log.Logger.Information($"AxoDialogLocator by PLC Opening: {e.SymbolOfDialogInstance}"); + Log.Logger.Verbose($"AxoDialogLocator by PLC Opening: {e.SymbolOfDialogInstance}"); await Refresh(); } private async void OnPlc_DialogRemoved(object? sender, AxoDialogEventArgs e) { - Log.Logger.Information($"AxoDialogLocator by PLC Closing: {e.SymbolOfDialogInstance}"); + Log.Logger.Verbose($"AxoDialogLocator by PLC Closing: {e.SymbolOfDialogInstance}"); await Refresh(); } diff --git a/src/core/src/AXOpen.Core.Blazor/AxoDialogs/Locator/AxoDialogLocatorService.cs b/src/core/src/AXOpen.Core.Blazor/AxoDialogs/Locator/AxoDialogLocatorService.cs index bb1596947..f95aaebdb 100644 --- a/src/core/src/AXOpen.Core.Blazor/AxoDialogs/Locator/AxoDialogLocatorService.cs +++ b/src/core/src/AXOpen.Core.Blazor/AxoDialogs/Locator/AxoDialogLocatorService.cs @@ -1,4 +1,4 @@ -using AXOpen.Base.Dialogs; +using AXOpen.Base.Dialogs; using AXSharp.Connector; using Serilog; @@ -140,7 +140,7 @@ protected async void HandleDialogInvocation_FromPlc(object? sender, AxoDialogEve { lock (_lockObject) { - Log.Logger.Information($"AxoDialogLocatorService invoke dialog (from Plc): {senderAsDialogMonitor.Dialog.Symbol}"); + Log.Logger.Verbose($"AxoDialogLocatorService invoke dialog (from Plc): {senderAsDialogMonitor.Dialog.Symbol}"); var exist = DisplayedDialogs.Any(p => p.Symbol == e.SymbolOfDialogInstance); if (!exist) @@ -164,7 +164,7 @@ public void HandleDialogClosing_FromPlc(object? sender, AxoDialogEventArgs e) { lock (_lockObject) { - Log.Logger.Information($"AxoDialogLocatorService remove displayed dialog (from Plc): {senderAsDialogMonitor.Dialog.Symbol}"); + Log.Logger.Verbose($"AxoDialogLocatorService remove displayed dialog (from Plc): {senderAsDialogMonitor.Dialog.Symbol}"); var exist = DisplayedDialogs.Any(p => p.Symbol == senderAsDialogMonitor.Dialog.Symbol); if (exist) @@ -186,7 +186,7 @@ public void RemoveDisplayedDialog(string dialogSymbol) { lock (_lockObject) { - Log.Logger.Information($"AxoDialogLocatorService removing displayed dialog: {dialogSymbol}"); + Log.Logger.Verbose($"AxoDialogLocatorService removing displayed dialog: {dialogSymbol}"); var exist = DisplayedDialogs.Any(p => p.Symbol == dialogSymbol); if (exist) @@ -235,4 +235,4 @@ public void Dispose() _observedDialogs.Clear(); } } -} \ No newline at end of file +} diff --git a/src/inspectors/src/AXOpen.Inspectors.blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor b/src/inspectors/src/AXOpen.Inspectors.blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor index ac31b4da5..629d0838d 100644 --- a/src/inspectors/src/AXOpen.Inspectors.blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor +++ b/src/inspectors/src/AXOpen.Inspectors.blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor @@ -1,4 +1,4 @@ -@namespace AXOpen.Inspectors +@namespace AXOpen.Inspectors @using System.Globalization @using AXOpen.Core.Blazor.AxoDialogs @using AXSharp.Connector.Localizations @@ -57,10 +57,13 @@ @code { + private string? currentUrl; string InspectionDescription { get; set; } + string InspectionId { get; set; } + eInspectorType InspectorType { get; set; } async Task GetInspectorType() @@ -72,8 +75,9 @@ { currentUrl = NavigationManager.ToBaseRelativePath(NavigationManager.Uri); NavigationManager.LocationChanged += OnLocationChanged; - + InspectionDescription = await Component._inspectionDetails.GetAsync(CultureInfo.CurrentCulture); + InspectionId = Component._inspectionDetails.LastValue; InspectorType = await GetInspectorType(); return base.OnInitializedAsync(); } diff --git a/src/inspectors/src/AXOpen.Inspectors.blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor.cs b/src/inspectors/src/AXOpen.Inspectors.blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor.cs index 35658b9b5..a4d42796d 100644 --- a/src/inspectors/src/AXOpen.Inspectors.blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor.cs +++ b/src/inspectors/src/AXOpen.Inspectors.blazor/AxoInspectorDialog/AxoInspectorDialogDialogView.razor.cs @@ -1,4 +1,4 @@ -using AXOpen.Core; +using AXOpen.Core; using AXOpen.Core.Blazor.AxoDialogs; using AXOpen.Logging; using AXSharp.Connector; @@ -17,6 +17,11 @@ namespace AXOpen.Inspectors public partial class AxoInspectorDialogDialogView : AxoDialogBaseView, IDisposable { + private string? InspectorDescription() + { + return InspectionId; + } + public bool RetryDisabled { get; set; } = false; protected override void OnAfterRender(bool firstRender) @@ -56,7 +61,7 @@ public async Task Retry() base.Component._dialogueRetry.Edit = true; await base.CloseDialogsWithSignalR(); var identity = (await _asp.GetAuthenticationStateAsync()).User.Identity; - AxoApplication.Current.Logger.Information($"{nameof(Retry)} of '{Component.HumanReadable}' was executed.", identity); + AxoApplication.Current.Logger.Information($"{nameof(Retry)} of '{InspectorDescription()}' was executed.", identity); } else { @@ -69,14 +74,14 @@ public async Task Terminate() base.Component._dialogueTerminate.Edit = true; await base.CloseDialogsWithSignalR(); var identity = (await _asp.GetAuthenticationStateAsync()).User.Identity; - AxoApplication.Current.Logger.Information($"{nameof(Terminate)} of '{Component.HumanReadable}' was executed.", identity); + AxoApplication.Current.Logger.Information($"{nameof(Terminate)} of '{InspectorDescription()}' was executed.", identity); } public async Task Override() { base.Component._dialogueOverride.Edit = true; await base.CloseDialogsWithSignalR(); var identity = (await _asp.GetAuthenticationStateAsync()).User.Identity; - AxoApplication.Current.Logger.Information($"{nameof(Override)} of '{Component.HumanReadable}' was executed.", identity); + AxoApplication.Current.Logger.Information($"{nameof(Override)} of '{InspectorDescription()}' was executed.", identity); } From bb4739a6163a3e405c8a7e69b5e4fd62c4ce3453 Mon Sep 17 00:00:00 2001 From: Peter Kurhajec <61538034+PTKu@users.noreply.github.com> Date: Tue, 3 Mar 2026 13:47:47 +0100 Subject: [PATCH 05/13] Enhance messaging system with requalification and suspension features, update logging for step timeouts, and improve UI handling for potential issues. --- .../src/AxoMessenger/IAxoMessengerService.st | 29 +++++ .../AxoSequencer/AxoSequencer.st | 100 +++++++++++++++++- .../src/AxoCoordination/AxoStep/AxoStep.st | 4 +- .../src/AxoMessaging/Static/AxoMessenger.st | 61 ++++++++--- .../Static/AxoMessengerService.st | 14 +++ .../src/AxoMessaging/eAxoMessageCategory.st | 22 +++- src/core/ctrl/src/abstractions/NULLs.st | 11 ++ .../Static/AxoMessaging_UnitTests.st | 33 ++++++ .../AxoComponentContainerView.razor.cs | 7 +- .../AxoComponent/AxoComponentView.razor.cs | 7 +- .../Static/AxoMessengerView.razor | 14 ++- .../AxoObject/AxoObjectDiagnosticsView.razor | 7 +- .../src/AXOpen.Core/AxoLogger/AxoLogger.cs | 6 +- .../AxoMessenger/Static/AxoMessenger.cs | 2 +- 14 files changed, 285 insertions(+), 32 deletions(-) diff --git a/src/abstractions/ctrl/src/AxoMessenger/IAxoMessengerService.st b/src/abstractions/ctrl/src/AxoMessenger/IAxoMessengerService.st index 5ba71e029..25ffd3405 100644 --- a/src/abstractions/ctrl/src/AxoMessenger/IAxoMessengerService.st +++ b/src/abstractions/ctrl/src/AxoMessenger/IAxoMessengerService.st @@ -5,8 +5,37 @@ NAMESPACE AXOpen.Core inMessegenger : IAxoMessenger; END_VAR END_METHOD + /// + /// Suspends the messaging system. When suspended, messages will not be sent to subscribers until the system is resumed. + /// This is useful for scenarios where you want to temporarily prevent messages from being processed. + /// METHOD SuspendMessaging END_METHOD + + /// + /// Resumes the messaging system. When resumed, messages that arose while the system was suspended will NOT be sent to subscribers. + /// METHOD ResumeMessaging END_METHOD + + /// + /// Checks if the messaging system is currently suspended. + /// Returns true if the messaging system is suspended, false otherwise. + /// METHOD IsSuspended : BOOL END_METHOD + + /// + /// Requalifies the message category for downstream messages. + /// This is used to ensure that messages that are sent from a downstream component are categorized correctly, + /// even if the upstream component has a different message category. + /// + METHOD RequalifyDownstreamMessages + VAR_INPUT + inMessageCategory : AXOpen.Messaging.eAxoMessageCategory; + END_VAR + END_METHOD + + /// + /// Gets the requalified message category for downstream messages. + /// + METHOD GetRequalifiedMessageCategory : AXOpen.Messaging.eAxoMessageCategory END_METHOD END_INTERFACE END_NAMESPACE diff --git a/src/core/ctrl/src/AxoCoordination/AxoSequencer/AxoSequencer.st b/src/core/ctrl/src/AxoCoordination/AxoSequencer/AxoSequencer.st index 455bf584e..69f6c8063 100644 --- a/src/core/ctrl/src/AxoCoordination/AxoSequencer/AxoSequencer.st +++ b/src/core/ctrl/src/AxoCoordination/AxoSequencer/AxoSequencer.st @@ -1,3 +1,5 @@ +USING AXOpen.Messaging; +USING AXOpen.Messaging.Static; NAMESPACE AXOpen.Core USING System.Strings; {S7.extern=ReadWrite} @@ -49,7 +51,6 @@ NAMESPACE AXOpen.Core END_IF; Open := FALSE; - SUPER.SetSuspendMultipleExecuteCallCheck(TRUE); StepForwardCommand.SetSuspendMultipleExecuteCallCheck(TRUE); @@ -57,6 +58,9 @@ NAMESPACE AXOpen.Core StepBackwardCommand.SetSuspendMultipleExecuteCallCheck(TRUE); IF SUPER.Execute() THEN + // Resets the message category requalification to default value of None at the beginning of each sequence execution to avoid unexpected message category requalifications caused by previous sequence executions. + _context.GetMessengerService().RequalifyDownstreamMessages(eAxoMessageCategory#None); + IF _context = NULL THEN RETURN; END_IF; @@ -83,6 +87,10 @@ NAMESPACE AXOpen.Core END_IF; END_METHOD + VAR PUBLIC + _msgStepTimedOut : AxoStepTimedOutMessenger; + END_VAR + METHOD INTERNAL Execute : BOOL VAR_INPUT step : IAxoStep; @@ -98,7 +106,6 @@ NAMESPACE AXOpen.Core END_IF; _step := step; - IF(_coordinatorState = AxoCoordinatorStates#Configuring) THEN THIS.DetermineOrder(step); END_IF; @@ -210,6 +217,21 @@ NAMESPACE AXOpen.Core CurrentStep := _refStep^; END_IF; + IF(THIS.MaxSequenceDuration = LT#0s) THEN + THIS.MaxSequenceDuration := LT#10s; // Default value for max sequence duration to 10 seconds if not set + END_IF; + + // We will only report step timeout when the step duration exceeds the MaxSequenceDuration, + // which is set for the whole sequence, to avoid too much noise in the logs. + IF(THIS.CurrentStep.Duration > THIS.MaxSequenceDuration) THEN + IF(Execute) THEN + _context.GetMessengerService().RequalifyDownstreamMessages(eAxoMessageCategory#Error); + _msgStepTimedOut.Activate(THIS, _refStep); + END_IF; + ELSE + _msgStepTimedOut.Deactivate(THIS, _refStep); + END_IF; + // IF(THIS.CurrentOrder + ULINT#1 = step.GetStepOrder() OR (THIS.CurrentOrder = THIS.GetNumberOfConfiguredSteps() AND step.GetStepOrder() = UINT#1)) THEN // _refStep ?= step; // AfterStep := _refStep^; @@ -443,6 +465,78 @@ NAMESPACE AXOpen.Core END_VAR SteppingMode := inSteppingMode; END_METHOD + END_CLASS + + {S7.extern=ReadWrite} + CLASS PUBLIC AxoStepTimedOutMessenger EXTENDS AxoMessenger + + VAR CONSTANT + MSG_STEP_TIMED_OUT : STRING[254] := '<#Step timed out: #>'; + END_VAR + + VAR PRIVATE + _refObservedStep : REF_TO AxoStep; + END_VAR + + METHOD INTERNAL Activate + VAR_INPUT + inParent : IAxoObject; + inStep : REF_TO AXOpen.Core.AxoStep; + END_VAR + + VAR + _context : IAxoContext; + END_VAR + + IF(inStep = NULL) THEN + RETURN; + END_IF; + + IF(THIS.MessengerState = eAxoMessengerState#Idle && _refObservedStep <> inStep) THEN + THIS.MessengerState := eAxoMessengerState#ActiveAcknowledgeNotRequired; + _context := inParent.GetContext(); + Risen := _context.GetRtc().NowUTC(); + Fallen := LDATE_AND_TIME#1970-01-01-00:00:00.000; + Acknowledged := LDATE_AND_TIME#1970-01-01-00:00:00.000; + Category := eAxoMessageCategory#Error; + Message := System.Strings.Concat(MSG_STEP_TIMED_OUT, inStep^.GetStepDescription()); + MessageCode := ULINT#18446744073709551615; // No specific message code for step timeout + _context.GetLogger().Log(System.Strings.Concat(RISE_SIGNATURE, Message), AXOpen.Logging.eLogLevel#Error, THIS); + _refObservedStep := inStep; + END_IF; + + IF(THIS.MessengerState <> eAxoMessengerState#Idle && _refObservedStep = inStep) THEN + inParent.AggregateMessage(1); + END_IF; + END_METHOD + + + METHOD INTERNAL Deactivate + VAR_INPUT + inParent : IAxoObject; + inStep : REF_TO AXOpen.Core.AxoStep; + END_VAR + VAR + _context : IAxoContext; + END_VAR + + IF(_refObservedStep = NULL) THEN + RETURN; + END_IF; + + + IF(THIS.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired) THEN + _context := inParent.GetContext(); + Fallen := _context.GetRtc().NowUTC(); + Message :=System.Strings.Concat(MSG_STEP_TIMED_OUT, _refObservedStep^.GetStepDescription()); + MessageCode := ULINT#18446744073709551615; // No specific message code for step timeout + _context.GetLogger().Log(System.Strings.Concat(FALL_SIGNATURE, Message), AXOpen.Logging.eLogLevel#Error, THIS); + THIS.MessengerState := eAxoMessengerState#Idle; + END_IF; + + _refObservedStep := NULL; + + END_METHOD + END_CLASS - END_CLASS END_NAMESPACE diff --git a/src/core/ctrl/src/AxoCoordination/AxoStep/AxoStep.st b/src/core/ctrl/src/AxoCoordination/AxoStep/AxoStep.st index 5401779fc..ef3445f21 100644 --- a/src/core/ctrl/src/AxoCoordination/AxoStep/AxoStep.st +++ b/src/core/ctrl/src/AxoCoordination/AxoStep/AxoStep.st @@ -1,3 +1,4 @@ +USING AXOpen.Messaging.Static; NAMESPACE AXOpen.Core {#ix-prop: public string Description} {S7.extern=ReadWrite} @@ -152,9 +153,6 @@ NAMESPACE AXOpen.Core ELSIF (SequencerContainer <> NULL) THEN ExecuteInternal := SequencerContainer^.Execute(THIS, Enable); END_IF; - - - // Selector ?= coord; // IF(coord <> NULL) THEN Sequencer^.ExecuteWithSelector(THIS, Enable); END_IF; diff --git a/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st b/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st index c0b64cce4..7536369e9 100644 --- a/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st +++ b/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st @@ -32,6 +32,17 @@ NAMESPACE AXOpen.Messaging.Static VAR PRIVATE _context : IAxoContext; END_VAR + + VAR PRIVATE + {#ix-attr:[ReadOnly()]} + _requalifiedToCategory : eAxoMessageCategory := eAxoMessageCategory#None; // This property is used to store the new category of the message in case it gets requalified by the messenger service configuration. + END_VAR + + VAR CONSTANT PROTECTED + RISE_SIGNATURE : STRING[4] := '^ : '; + FALL_SIGNATURE : STRING[4] := 'v : '; + END_VAR + /// /// Ensures the inicialization of the instance, so as the deactivation of the message. Must be called cyclically. @@ -41,15 +52,12 @@ NAMESPACE AXOpen.Messaging.Static inObject : IAxoObject; END_VAR - IF _context = NULL THEN - IF inObject.GetContext() = NULL THEN - RETURN; - END_IF; - - SUPER.Run(inObject); - _context := inObject.GetContext(); - END_IF; - + SUPER.Run(inObject); + _context := THIS.GetContext(); + IF(NOT THIS.IsValid()) THEN + RETURN; + END_IF; + IF THIS.MessengerState = eAxoMessengerState#ActiveAcknowledgeRequired AND NOT AcknowledgementRequired THEN THIS.MessengerState := eAxoMessengerState#ActiveAcknowledgeNotRequired; END_IF; @@ -91,8 +99,14 @@ NAMESPACE AXOpen.Messaging.Static METHOD PUBLIC Activate : AXOpen.Messaging.Static.IAxoMessageProperties VAR_INPUT _messageCode : ULINT; + inCategory : eAxoMessageCategory; + END_VAR + VAR _category : eAxoMessageCategory; END_VAR + + _category := inCategory; + IF _context = NULL THEN _context := THIS.GetContext(); END_IF; @@ -110,25 +124,29 @@ NAMESPACE AXOpen.Messaging.Static IF _messageCode = ULINT#0 THEN RETURN; END_IF; + + // "Complete new" activation IF THIS.MessengerState = eAxoMessengerState#Idle AND MessageCode = ULINT#0 AND ActiveContextCount = ULINT#0 THEN Risen := _context.GetRtc().NowUTC(); Fallen := LDATE_AND_TIME#1970-01-01-00:00:00.000; Acknowledged := LDATE_AND_TIME#1970-01-01-00:00:00.000; - _context.GetLogger().Log('$5E', THIS.ToLogLevel(_category), THIS, _messageCode); + _context.GetLogger().Log(RISE_SIGNATURE, THIS.ToLogLevel(_category), THIS, _messageCode); MessageCode := _messageCode; Category := _category; + _requalifiedToCategory := eAxoMessageCategory#None; // AcknowledgementRequired := Category >= eAxoMessageCategory#Error; END_IF; - + // "Reactivation" in case of acknowledgable alarm rised, falled and rised again without acknowledgement IF THIS.MessengerState = eAxoMessengerState#InactiveWaitingForAcknowledge AND MessageCode = _messageCode AND ActiveContextCount = ULINT#0 THEN Risen := _context.GetRtc().NowUTC(); Fallen := LDATE_AND_TIME#1970-01-01-00:00:00.000; - Acknowledged := LDATE_AND_TIME#1970-01-01-00:00:00.000; + Acknowledged := LDATE_AND_TIME#1970-01-01-00:00:00.000; + _requalifiedToCategory := eAxoMessageCategory#None; END_IF; IF MessageCode = _messageCode THEN @@ -146,6 +164,21 @@ NAMESPACE AXOpen.Messaging.Static END_IF; END_IF; + // This will requalify the message category in case the messenger service is configured to do so. + // Only potential messages can be requalified to Warning or Error, any other category will not be requalified and will be logged as configured by the user. + IF(_category = eAxoMessageCategory#Potential + AND _context.GetMessengerService().GetRequalifiedMessageCategory() <> eAxoMessageCategory#None + AND _requalifiedToCategory = eAxoMessageCategory#None) THEN + Risen := _context.GetRtc().NowUTC(); + Fallen := LDATE_AND_TIME#1970-01-01-00:00:00.000; + Acknowledged := LDATE_AND_TIME#1970-01-01-00:00:00.000; + MessageCode := _messageCode; + Category := _context.GetMessengerService().GetRequalifiedMessageCategory(); + _requalifiedToCategory := Category; + _context.GetLogger().Log(RISE_SIGNATURE, THIS.ToLogLevel(Category), THIS, _messageCode); + END_IF; + + Activate := THIS; END_METHOD @@ -187,7 +220,7 @@ NAMESPACE AXOpen.Messaging.Static END_IF; END_METHOD - METHOD PRIVATE Deactivate + METHOD PROTECTED Deactivate VAR_INPUT _messageCode : ULINT; _logLevel : eLogLevel; @@ -210,7 +243,7 @@ NAMESPACE AXOpen.Messaging.Static IF MessageCode = _messageCode THEN ActiveContextCount := ULINT#0; Fallen := _context.GetRtc().NowUTC(); - _context.GetLogger().Log('$76', _logLevel, THIS, _messageCode); + _context.GetLogger().Log(FALL_SIGNATURE, _logLevel, THIS, _messageCode); IF THIS.MessengerState = eAxoMessengerState#ActiveAcknowledgeRequired THEN THIS.MessengerState := eAxoMessengerState#InactiveWaitingForAcknowledge; ELSIF THIS.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired THEN diff --git a/src/core/ctrl/src/AxoMessaging/Static/AxoMessengerService.st b/src/core/ctrl/src/AxoMessaging/Static/AxoMessengerService.st index fd547b2ef..1fbaf58d1 100644 --- a/src/core/ctrl/src/AxoMessaging/Static/AxoMessengerService.st +++ b/src/core/ctrl/src/AxoMessaging/Static/AxoMessengerService.st @@ -95,6 +95,20 @@ NAMESPACE AXOpen.Messaging IsSuspended := _isSuspended; END_METHOD + VAR PRIVATE + _requalificationCategory : eAxoMessageCategory := eAxoMessageCategory#None; + END_VAR + + METHOD PUBLIC RequalifyDownstreamMessages + VAR_INPUT + inMessageCategory : eAxoMessageCategory; + END_VAR + _requalificationCategory := inMessageCategory; + END_METHOD + + METHOD PUBLIC GetRequalifiedMessageCategory : eAxoMessageCategory + GetRequalifiedMessageCategory := _requalificationCategory; + END_METHOD END_CLASS diff --git a/src/core/ctrl/src/AxoMessaging/eAxoMessageCategory.st b/src/core/ctrl/src/AxoMessaging/eAxoMessageCategory.st index d390a55af..8e6c783f8 100644 --- a/src/core/ctrl/src/AxoMessaging/eAxoMessageCategory.st +++ b/src/core/ctrl/src/AxoMessaging/eAxoMessageCategory.st @@ -5,20 +5,36 @@ NAMESPACE AXOpen.Messaging /// ATTENTION: Values must be multiply of 100 /// eAxoMessageCategory : INT - ( + ( + /// + /// No category. + /// This is used to indicate that the message does not have any importance and should be ignored by the system. + /// Do not use this category for messages that have to be delivered to the user, even if such information is not critical. + /// + None := 0, + + /// /// Info message. /// Use when you want to deliver information to the user, that has only informative character and does not adversely affect a process. /// Info := 100, - + + /// + /// Potential problem message. + /// Use this category when you want to report to the user an information about a potential problem, that does not necessarily affect a process + /// but may cause a problem. This is typically used when certain conditions is expected to happen within a process that did not happen yet, + /// this category is aimed to be later automatically requalified to Warning or Error by coordination primitive if the expected conditions did not happen within expected time. + /// + Potential := 150, + /// /// Warning message. /// Use this category when you want to report to the user an information about a possible problem, that may adversly affect a process. /// Information in this cateogory aims to help the user to identify a problem, the cause of such problem does not necessarily stops the process. /// Warning := 200, - + /// /// Error message. /// Use this category when there is a failure that cannot be immediately recovered and an intervention is needed. This is typically a situation when a device fails diff --git a/src/core/ctrl/src/abstractions/NULLs.st b/src/core/ctrl/src/abstractions/NULLs.st index e5422295f..6ef161f31 100644 --- a/src/core/ctrl/src/abstractions/NULLs.st +++ b/src/core/ctrl/src/abstractions/NULLs.st @@ -185,6 +185,17 @@ NAMESPACE AXOpen.Core METHOD PUBLIC IsSuspended : BOOL IsSuspended := _isSuspended; END_METHOD + + METHOD PUBLIC RequalifyDownstreamMessages + VAR_INPUT + inMessageCategory : eAxoMessageCategory; + END_VAR + ; + END_METHOD + + METHOD PUBLIC GetRequalifiedMessageCategory : eAxoMessageCategory + ; + END_METHOD END_CLASS END_NAMESPACE diff --git a/src/core/ctrl/test/AxoMessaging/Static/AxoMessaging_UnitTests.st b/src/core/ctrl/test/AxoMessaging/Static/AxoMessaging_UnitTests.st index ed0b7bc41..bc3f4eb22 100644 --- a/src/core/ctrl/test/AxoMessaging/Static/AxoMessaging_UnitTests.st +++ b/src/core/ctrl/test/AxoMessaging/Static/AxoMessaging_UnitTests.st @@ -225,6 +225,7 @@ NAMESPACE AXOpen.AxoMessagingStatic_UnitTests VAR PRIVATE _IsSuspended : BOOL := FALSE; + _requalificationCategory : eAxoMessageCategory := eAxoMessageCategory#None; END_VAR METHOD PUBLIC QueueMessage : BOOL @@ -251,6 +252,17 @@ NAMESPACE AXOpen.AxoMessagingStatic_UnitTests METHOD PUBLIC IsSuspended : BOOL IsSuspended :=_IsSuspended; END_METHOD + + METHOD PUBLIC RequalifyDownstreamMessages + VAR_INPUT + inMessageCategory : eAxoMessageCategory; + END_VAR + _requalificationCategory := inMessageCategory; + END_METHOD + + METHOD PUBLIC GetRequalifiedMessageCategory : eAxoMessageCategory + GetRequalifiedMessageCategory := _requalificationCategory; + END_METHOD END_CLASS {S7.extern=ReadWrite} @@ -400,6 +412,27 @@ NAMESPACE AXOpen.AxoMessagingStatic_UnitTests END_METHOD + {Test} + METHOD PUBLIC category_should_be_requalified_when_requalification_changes_while_message_is_active + _suti.InjectMessengerService(_serviceSpy); + + _suti.Open(); + _suti.InitializeRootObject(_suti._object); + _suti._object._messenger.Serve(_suti._object); + _serviceSpy.RequalifyDownstreamMessages(eAxoMessageCategory#None); + _suti._object._messenger.Activate(UINT#1, eAxoMessageCategory#Potential); + Assert.Equal(TRUE, _suti._object._messenger.Category = eAxoMessageCategory#Potential); + _suti.Close(); + + _suti.Open(); + _suti._object._messenger.Serve(_suti._object); + _serviceSpy.RequalifyDownstreamMessages(eAxoMessageCategory#Error); + _suti._object._messenger.Activate(UINT#1, eAxoMessageCategory#Potential); + Assert.Equal(TRUE, _suti._object._messenger.IsActive()); + Assert.Equal(TRUE, _suti._object._messenger.Category = eAxoMessageCategory#Error); + _suti.Close(); + END_METHOD + {Test} METHOD PUBLIC post_should_enqueue_message_with_sender_and_text diff --git a/src/core/src/AXOpen.Core.Blazor/AxoComponent/AxoCompnentsBase/AxoComponentContainerView.razor.cs b/src/core/src/AXOpen.Core.Blazor/AxoComponent/AxoCompnentsBase/AxoComponentContainerView.razor.cs index 3937acf8b..3f8c7d3f3 100644 --- a/src/core/src/AXOpen.Core.Blazor/AxoComponent/AxoCompnentsBase/AxoComponentContainerView.razor.cs +++ b/src/core/src/AXOpen.Core.Blazor/AxoComponent/AxoCompnentsBase/AxoComponentContainerView.razor.cs @@ -1,4 +1,4 @@ -using AXOpen.Messaging; +using AXOpen.Messaging; using AXOpen.Messaging.Static; using AXOpen.VisualComposer.Components.VisualComposerItem; using AXSharp.Presentation.Blazor.Controls.RenderableContent; @@ -62,6 +62,7 @@ public AxoMessageProvider? MessageProvider eAlarmLevel.NoAlarms => "", eAlarmLevel.Unacknowledged => "animate-pulse-danger badge-warning", eAlarmLevel.ActiveInfo => "animate-pulse-danger badge-info", + eAlarmLevel.ActivePotential => "animate-pulse-danger badge-info", eAlarmLevel.ActiveWarnings => "animate-pulse-danger badge-warning", eAlarmLevel.ActiveErrors => "animate-pulse-danger badge-danger", _ => "" @@ -106,6 +107,7 @@ private eAlarmLevel _alarmLevel return seriousness switch { eAxoMessageCategory.Info => eAlarmLevel.ActiveInfo, + eAxoMessageCategory.Potential => eAlarmLevel.ActivePotential, eAxoMessageCategory.Warning => eAlarmLevel.ActiveWarnings, eAxoMessageCategory.Error or eAxoMessageCategory.ProgrammingError or eAxoMessageCategory.Critical => eAlarmLevel.ActiveErrors, _ => eAlarmLevel.NoAlarms @@ -126,6 +128,7 @@ private eAlarmLevel _alarmLevel eAlarmLevel.NoAlarms => "", eAlarmLevel.Unacknowledged => "border-warning", eAlarmLevel.ActiveInfo => "border-info", + eAlarmLevel.ActivePotential => "border-info shadow-glow-info", eAlarmLevel.ActiveWarnings => "border-warning/20! shadow-glow-warning", eAlarmLevel.ActiveErrors => "border-danger/20! shadow-glow-danger", _ => "" @@ -137,6 +140,7 @@ private eAlarmLevel _alarmLevel eAlarmLevel.NoAlarms => "", eAlarmLevel.Unacknowledged => "bg-warning", eAlarmLevel.ActiveInfo => "bg-info", + eAlarmLevel.ActivePotential => "bg-info shadow-glow-info", eAlarmLevel.ActiveWarnings => "bg-warning/20! shadow-glow-warning", eAlarmLevel.ActiveErrors => "bg-danger/20! shadow-glow-danger", _ => "" @@ -148,6 +152,7 @@ private eAlarmLevel _alarmLevel eAlarmLevel.NoAlarms => "bg-background/80", eAlarmLevel.Unacknowledged => "bg-warning", eAlarmLevel.ActiveInfo => "bg-info", + eAlarmLevel.ActivePotential => "bg-info", eAlarmLevel.ActiveWarnings => "bg-warning/20! shadow-glow-warning", eAlarmLevel.ActiveErrors => "bg-danger/20! shadow-glow-danger", _ => "bg-background/80" diff --git a/src/core/src/AXOpen.Core.Blazor/AxoComponent/AxoComponentView.razor.cs b/src/core/src/AXOpen.Core.Blazor/AxoComponent/AxoComponentView.razor.cs index 1d6812741..4da19bd97 100644 --- a/src/core/src/AXOpen.Core.Blazor/AxoComponent/AxoComponentView.razor.cs +++ b/src/core/src/AXOpen.Core.Blazor/AxoComponent/AxoComponentView.razor.cs @@ -1,4 +1,4 @@ -using AXOpen.Messaging; +using AXOpen.Messaging; using AXOpen.Messaging.Static; using AXSharp.Connector; using AXOpen.Core; @@ -51,6 +51,8 @@ private eAlarmLevel _alarmLevel { case eAxoMessageCategory.Info: return eAlarmLevel.ActiveInfo; + case eAxoMessageCategory.Potential: + return eAlarmLevel.ActiveInfo; case eAxoMessageCategory.Warning: return eAlarmLevel.ActiveWarnings; case eAxoMessageCategory.Error: @@ -229,6 +231,7 @@ public enum eAlarmLevel NoAlarms, Unacknowledged, ActiveInfo, + ActivePotential, ActiveWarnings, ActiveErrors } @@ -248,4 +251,4 @@ public AxoComponentStatusView() IsControllable = false; } } -} \ No newline at end of file +} diff --git a/src/core/src/AXOpen.Core.Blazor/AxoMessenger/Static/AxoMessengerView.razor b/src/core/src/AXOpen.Core.Blazor/AxoMessenger/Static/AxoMessengerView.razor index 04fa94053..2cd4bb656 100644 --- a/src/core/src/AXOpen.Core.Blazor/AxoMessenger/Static/AxoMessengerView.razor +++ b/src/core/src/AXOpen.Core.Blazor/AxoMessenger/Static/AxoMessengerView.razor @@ -1,4 +1,4 @@ -@namespace AXOpen.Messaging.Static +@namespace AXOpen.Messaging.Static @inherits RenderableComplexComponentBase @using System.Security.Principal @using Operon.Icons @@ -99,6 +99,8 @@ { case eAxoMessageCategory.Info: return Localizer["SeverityInfo"]; + case eAxoMessageCategory.Potential: + return Localizer["PotentialIssue"]; case eAxoMessageCategory.Warning: return Localizer["SeverityWarning"]; case eAxoMessageCategory.Error: @@ -117,6 +119,8 @@ { case eAxoMessageCategory.Info: return "bg-linear-to-br from-info/20! from-0% to-background-light! to-50%"; + case eAxoMessageCategory.Potential: + return "bg-linear-to-br from-info/20! from-0% to-background-light! to-50%"; case eAxoMessageCategory.Warning: return "bg-linear-to-br from-warning/20! from-0% to-background-light! to-50%"; case eAxoMessageCategory.Error: @@ -135,8 +139,10 @@ { case eAxoMessageCategory.Info: return "shadow-glow-info"; + case eAxoMessageCategory.Potential: + return "shadow-glow-info"; case eAxoMessageCategory.Warning: - return "shadow-glow-warning"; + return "shadow-glow-warning"; case eAxoMessageCategory.Error: return "shadow-glow-danger"; case eAxoMessageCategory.ProgrammingError: @@ -153,6 +159,8 @@ { case eAxoMessageCategory.Info: return "bg-info"; + case eAxoMessageCategory.Potential: + return "bg-info"; case eAxoMessageCategory.Warning: return "bg-warning"; case eAxoMessageCategory.Error: @@ -181,4 +189,4 @@ _isDetailsExpanded = !_isDetailsExpanded; StateHasChanged(); } -} \ No newline at end of file +} diff --git a/src/core/src/AXOpen.Core.Blazor/AxoObject/AxoObjectDiagnosticsView.razor b/src/core/src/AXOpen.Core.Blazor/AxoObject/AxoObjectDiagnosticsView.razor index 969e71e3b..af7416b17 100644 --- a/src/core/src/AXOpen.Core.Blazor/AxoObject/AxoObjectDiagnosticsView.razor +++ b/src/core/src/AXOpen.Core.Blazor/AxoObject/AxoObjectDiagnosticsView.razor @@ -1,4 +1,4 @@ -@namespace AXOpen.Core +@namespace AXOpen.Core @inherits RenderableComplexComponentBase @using AXOpen.Core @using AXOpen.Messaging.Static @@ -271,6 +271,7 @@ return category switch { eAxoMessageCategory.Info => Localizer["SeverityInfo"], + eAxoMessageCategory.Potential => Localizer["PotentialIssue"], eAxoMessageCategory.Warning => Localizer["SeverityWarning"], eAxoMessageCategory.Error => Localizer["SeverityError"], eAxoMessageCategory.ProgrammingError => Localizer["SeverityProgrammingError"], @@ -285,6 +286,8 @@ { case eAxoMessageCategory.Info: return "badge-info"; + case eAxoMessageCategory.Potential: + return "badge-info"; case eAxoMessageCategory.Warning: return "badge-warning"; case eAxoMessageCategory.Error: @@ -305,6 +308,8 @@ { case eAxoMessageCategory.Info: return "bg-info/10!"; + case eAxoMessageCategory.Potential: + return "bg-info/10!"; case eAxoMessageCategory.Warning: return "bg-warning/10!"; case eAxoMessageCategory.Error: diff --git a/src/core/src/AXOpen.Core/AxoLogger/AxoLogger.cs b/src/core/src/AXOpen.Core/AxoLogger/AxoLogger.cs index c1222a077..071837289 100644 --- a/src/core/src/AXOpen.Core/AxoLogger/AxoLogger.cs +++ b/src/core/src/AXOpen.Core/AxoLogger/AxoLogger.cs @@ -58,9 +58,13 @@ await Task.Run(async () => switch (sender) { + case AxoStepTimedOutMessenger timedOutMessenger: + level = (eLogLevel)entry.Level.LastValue; + message = $"{entry.Message.LastValue}"; + break; case AxoMessenger messenger: await messenger.ReadAsync(); - message = $"{entry.Message.LastValue} : {messenger.GetMessageText(entry.MessageCode.LastValue)}"; + message = $"{entry.Message.LastValue} {messenger.GetMessageText(messenger.MessageCode.LastValue)}"; break; case AxoStep step: await step.ReadAsync(); diff --git a/src/core/src/AXOpen.Core/AxoMessenger/Static/AxoMessenger.cs b/src/core/src/AXOpen.Core/AxoMessenger/Static/AxoMessenger.cs index 06537dd6e..af368f270 100644 --- a/src/core/src/AXOpen.Core/AxoMessenger/Static/AxoMessenger.cs +++ b/src/core/src/AXOpen.Core/AxoMessenger/Static/AxoMessenger.cs @@ -212,7 +212,7 @@ public string GetMessageText(ulong messageCode) //18446744073709551615 if (messageCode == ulong.MaxValue) { - return this.Message.LastValue; + return this.Message.GetCyclic(); } string retVal = ""; From 8cf1592ef7debb85deef569bd57b0f2b7aefe689 Mon Sep 17 00:00:00 2001 From: Peter Kurhajec <61538034+PTKu@users.noreply.github.com> Date: Tue, 3 Mar 2026 13:47:58 +0100 Subject: [PATCH 06/13] Update messenger conditions to use 'Warning' and 'Potential' categories for improved logging clarity --- src/components.pneumatics/ctrl/src/AxoCylinder.st | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components.pneumatics/ctrl/src/AxoCylinder.st b/src/components.pneumatics/ctrl/src/AxoCylinder.st index 68af1bd77..098d3795a 100644 --- a/src/components.pneumatics/ctrl/src/AxoCylinder.st +++ b/src/components.pneumatics/ctrl/src/AxoCylinder.st @@ -115,7 +115,7 @@ NAMESPACE AXOpen.Components.Pneumatics _Messenger.Serve(THIS); - _Messenger.ActivateOnCondition(UINT#3, _OutSensor AND _InSensor, eAxoMessageCategory#Error); + _Messenger.ActivateOnCondition(UINT#3, _OutSensor AND _InSensor, eAxoMessageCategory#Warning); IF(_StopTask.Execute(THIS)) THEN _MoveInSignal := FALSE; @@ -136,8 +136,8 @@ NAMESPACE AXOpen.Components.Pneumatics _MoveToOutIsBusy := _MoveOutTask.IsBusy(); - _Messenger.ActivateOnCondition(UINT#1, (_MoveToOutIsBusy AND NOT _MoveToOutIsSuspended AND _MoveOutTask.Duration >= T#10S), eAxoMessageCategory#Error); - _Messenger.ActivateOnCondition(UINT#9, (_MoveOutTask.IsDone() AND NOT _OutSensor), eAxoMessageCategory#Warning); + _Messenger.ActivateOnCondition(UINT#1, (_MoveToOutIsBusy AND NOT _MoveToOutIsSuspended AND _MoveOutTask.Duration >= T#10S), eAxoMessageCategory#Potential); + _Messenger.ActivateOnCondition(UINT#9, (_MoveOutTask.IsDone() AND NOT _OutSensor), eAxoMessageCategory#Potential); IF(_MoveInTask.Execute(THIS)) THEN @@ -151,8 +151,8 @@ NAMESPACE AXOpen.Components.Pneumatics _MoveToInIsBusy := _MoveInTask.IsBusy(); - _Messenger.ActivateOnCondition(UINT#2, (_MoveToInIsBusy AND NOT _MoveToInIsSuspended AND _MoveInTask.Duration >= T#10S), eAxoMessageCategory#Error); - _Messenger.ActivateOnCondition(UINT#8, (_MoveInTask.IsDone() AND NOT _InSensor), eAxoMessageCategory#Warning); + _Messenger.ActivateOnCondition(UINT#2, (_MoveToInIsBusy AND NOT _MoveToInIsSuspended), eAxoMessageCategory#Potential); + _Messenger.ActivateOnCondition(UINT#8, (_MoveInTask.IsDone() AND NOT _InSensor), eAxoMessageCategory#Potential); outMoveInSignal := _MoveInSignal AND NOT _MoveToInIsSuspended; From 44fc27acba8dec79be965cbebbb61fa3e2f356e5 Mon Sep 17 00:00:00 2001 From: Peter Kurhajec <61538034+PTKu@users.noreply.github.com> Date: Tue, 3 Mar 2026 15:04:24 +0100 Subject: [PATCH 07/13] Standardize severity localization keys and UI usage Refactored severity label keys in all resource files to use "Info", "Warning", "Error_", "System", and "Critical" for consistency across languages and components. Updated AxoMessengerView.razor and AxoObjectDiagnosticsView.razor to use new keys. Added ConvertToBadge helper for severity-based badge styling. Commented out "StateLabel" badge in AxoMessengerView.razor. SeverityOptions in AxoObjectDiagnosticsView.razor now skips the first enum value. Renamed "HideDetails" and "ShowDetails" keys to avoid duplicates. Minor resource file formatting fixes. --- .../Static/AxoMessengerView.razor | 36 ++++++++++++++----- .../AxoObject/AxoObjectDiagnosticsView.razor | 14 ++++---- .../Properties/AxOpenCoreResources.de-DE.resx | 16 ++++----- .../Properties/AxOpenCoreResources.de.resx | 12 +++---- .../Properties/AxOpenCoreResources.es-ES.resx | 16 ++++----- .../Properties/AxOpenCoreResources.es.resx | 12 +++---- .../Properties/AxOpenCoreResources.hu-HU.resx | 16 ++++----- .../Properties/AxOpenCoreResources.pl-PL.resx | 16 ++++----- .../Properties/AxOpenCoreResources.resx | 16 ++++----- .../Properties/AxOpenCoreResources.sk-SK.resx | 16 ++++----- .../Properties/AxOpenCoreResources.sk.resx | 12 +++---- 11 files changed, 101 insertions(+), 81 deletions(-) diff --git a/src/core/src/AXOpen.Core.Blazor/AxoMessenger/Static/AxoMessengerView.razor b/src/core/src/AXOpen.Core.Blazor/AxoMessenger/Static/AxoMessengerView.razor index 2cd4bb656..8ad925b30 100644 --- a/src/core/src/AXOpen.Core.Blazor/AxoMessenger/Static/AxoMessengerView.razor +++ b/src/core/src/AXOpen.Core.Blazor/AxoMessenger/Static/AxoMessengerView.razor @@ -9,7 +9,7 @@
-
+
@ConvertToInternalSeverityName((eAxoMessageCategory)Component.Category.LastValue)
@@ -18,7 +18,7 @@ @Component.GetMessageText() }
-
@StateLabel
+ @*
@StateLabel
*@
@@ -98,17 +98,17 @@ switch (category) { case eAxoMessageCategory.Info: - return Localizer["SeverityInfo"]; + return Localizer["Info"]; case eAxoMessageCategory.Potential: - return Localizer["PotentialIssue"]; + return Localizer["Potential"]; case eAxoMessageCategory.Warning: - return Localizer["SeverityWarning"]; + return Localizer["Warning"]; case eAxoMessageCategory.Error: - return Localizer["SeverityMinorFault"]; + return Localizer["Error"]; case eAxoMessageCategory.ProgrammingError: - return Localizer["SeverityMajorFault"]; + return Localizer["System"]; case eAxoMessageCategory.Critical: - return Localizer["SeverityCritical"]; + return Localizer["Critical"]; } return string.Empty; } @@ -133,6 +133,26 @@ return string.Empty; } + private static string ConvertToBadge(eAxoMessageCategory category) + { + switch (category) + { + case eAxoMessageCategory.Info: + return "badge badge-primary"; + case eAxoMessageCategory.Potential: + return "badge badge-primary"; + case eAxoMessageCategory.Warning: + return "badge badge-warning"; + case eAxoMessageCategory.Error: + return "badge badge-danger"; + case eAxoMessageCategory.ProgrammingError: + return "badge badge-danger"; + case eAxoMessageCategory.Critical: + return "badge badge-danger"; + } + return string.Empty; + } + private static string ConvertToInternalShadowGlowSeverityName(eAxoMessageCategory category) { switch (category) diff --git a/src/core/src/AXOpen.Core.Blazor/AxoObject/AxoObjectDiagnosticsView.razor b/src/core/src/AXOpen.Core.Blazor/AxoObject/AxoObjectDiagnosticsView.razor index af7416b17..462e29d34 100644 --- a/src/core/src/AXOpen.Core.Blazor/AxoObject/AxoObjectDiagnosticsView.razor +++ b/src/core/src/AXOpen.Core.Blazor/AxoObject/AxoObjectDiagnosticsView.razor @@ -270,12 +270,12 @@ { return category switch { - eAxoMessageCategory.Info => Localizer["SeverityInfo"], - eAxoMessageCategory.Potential => Localizer["PotentialIssue"], - eAxoMessageCategory.Warning => Localizer["SeverityWarning"], - eAxoMessageCategory.Error => Localizer["SeverityError"], - eAxoMessageCategory.ProgrammingError => Localizer["SeverityProgrammingError"], - eAxoMessageCategory.Critical => Localizer["SeverityCritical"], + eAxoMessageCategory.Info => Localizer["Info"], + eAxoMessageCategory.Potential => Localizer["Potential"], + eAxoMessageCategory.Warning => Localizer["Warning"], + eAxoMessageCategory.Error => Localizer["Error"], + eAxoMessageCategory.ProgrammingError => Localizer["System"], + eAxoMessageCategory.Critical => Localizer["Critical"], _ => string.Empty }; } @@ -428,7 +428,7 @@ private IJSObjectReference? module; private IEnumerable observedObjects = new List(); private AxoMessageProvider provider; - private static readonly eAxoMessageCategory[] SeverityOptions = Enum.GetValues().ToArray(); + private static readonly eAxoMessageCategory[] SeverityOptions = Enum.GetValues().Skip(1).ToArray(); private readonly HashSet _selectedSeverities = new(SeverityOptions); private bool _shouldBounce = false; private System.Threading.Timer? _bounceTimer; diff --git a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.de-DE.resx b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.de-DE.resx index 15db6ae52..660893a39 100644 --- a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.de-DE.resx +++ b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.de-DE.resx @@ -189,14 +189,14 @@ Aufgabe zurücksetzen - + Infos - + Warnung - - Kleinere Störung + + Fehler Major Fault @@ -204,10 +204,10 @@ Fehler - + Systemfehler - + Kritisch @@ -260,10 +260,10 @@ Keine Alarme anzuzeigen. - + Details ausblenden - + Details anzeigen diff --git a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.de.resx b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.de.resx index 0938b76df..f0d2f23ce 100644 --- a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.de.resx +++ b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.de.resx @@ -133,19 +133,19 @@ Aufgabe zurücksetzen - + Info - + Warnung - - Kleiner Fehler + + Fehler Großer Fehler - + Kritisch @@ -171,4 +171,4 @@ aktiv - + \ No newline at end of file diff --git a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.es-ES.resx b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.es-ES.resx index 5fa26fad3..d38bdcd05 100644 --- a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.es-ES.resx +++ b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.es-ES.resx @@ -189,14 +189,14 @@ Reiniciar tarea - + Información - + Advertencia - - Fallo menor + + Fallo Fallo grave @@ -204,10 +204,10 @@ Error - + Error del sistema - + Crítica @@ -260,10 +260,10 @@ No hay alarmas para mostrar. - + Ocultar detalles - + Mostrar detalles diff --git a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.es.resx b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.es.resx index 5e52a9c75..b291e8dfc 100644 --- a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.es.resx +++ b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.es.resx @@ -133,19 +133,19 @@ Restablecer tarea - + Info - + Advertencia - - Fallo menor + + Fallo Fallo mayor - + Crítico @@ -171,4 +171,4 @@ activo - + \ No newline at end of file diff --git a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.hu-HU.resx b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.hu-HU.resx index 64eb644c1..1997bb0de 100644 --- a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.hu-HU.resx +++ b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.hu-HU.resx @@ -189,14 +189,14 @@ Feladat alaphelyzetbe állítása - + Info - + Figyelmeztetés - - Kisebb hiba + + Hiba Fő hiba @@ -204,10 +204,10 @@ Hiba - + Rendszerhiba - + Kritikus @@ -260,10 +260,10 @@ Nincsenek megjelenítendő riasztások. - + Részletek elrejtése - + Részletek megjelenítése diff --git a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.pl-PL.resx b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.pl-PL.resx index 473578a71..eef4cea96 100644 --- a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.pl-PL.resx +++ b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.pl-PL.resx @@ -189,14 +189,14 @@ Resetowanie zadania - + Info - + Ostrzeżenie - - Drobna usterka + + Usterka Główny błąd @@ -204,10 +204,10 @@ Błąd - + Błąd systemu - + Krytyczny @@ -260,10 +260,10 @@ Brak alarmów do wyświetlenia. - + Ukryj szczegóły - + Pokaż szczegóły diff --git a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.resx b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.resx index a1870407a..e6d6783a3 100644 --- a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.resx +++ b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.resx @@ -133,14 +133,14 @@ Reset task - + Info - + Warning - - Minor Fault + + Error Major Fault @@ -148,10 +148,10 @@ Error - + System Error - + Critical @@ -206,10 +206,10 @@ No alarms to display. - + Hide details - + Show details diff --git a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.sk-SK.resx b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.sk-SK.resx index 3c7f02390..7ce98b6ff 100644 --- a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.sk-SK.resx +++ b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.sk-SK.resx @@ -189,14 +189,14 @@ Obnovenie úlohy - + Informácie - + Upozornenie - - Menšia porucha + + Chyba Hlavná porucha @@ -204,10 +204,10 @@ Chyba - + Chyba systému - + Kritické @@ -260,10 +260,10 @@ Žiadne alarmy na zobrazenie. - + Skryť podrobnosti - + Zobraziť podrobnosti diff --git a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.sk.resx b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.sk.resx index e37e0a33e..fc219282a 100644 --- a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.sk.resx +++ b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.sk.resx @@ -133,19 +133,19 @@ Resetovať úlohu - + Info - + Varovanie - - Menšia chyba + + Chyba Väčšia chyba - + Kritický @@ -171,4 +171,4 @@ aktívny - + \ No newline at end of file From e7e557b3b047b9f6df27e4a3b3d2c9b3de3688fd Mon Sep 17 00:00:00 2001 From: Peter Kurhajec <61538034+PTKu@users.noreply.github.com> Date: Tue, 3 Mar 2026 16:26:17 +0100 Subject: [PATCH 08/13] Add requalification tests for message categories in AxoMessenger --- .../src/AxoMessaging/Static/AxoMessenger.st | 1 + .../Static/AxoMessaging_UnitTests.st | 241 ++++++++++++++++++ 2 files changed, 242 insertions(+) diff --git a/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st b/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st index 7536369e9..e9bd02703 100644 --- a/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st +++ b/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st @@ -154,6 +154,7 @@ NAMESPACE AXOpen.Messaging.Static IF ActiveContextCount = ULINT#0 OR Risen = LDATE_AND_TIME#1970-01-01-00:00:00.000 THEN THIS.MessengerState := eAxoMessengerState#InvalidImplementation; THIS.Category := eAxoMessageCategory#ProgrammingError; + RETURN; END_IF; IF THIS.MessengerState <> eAxoMessengerState#ActiveAlreadyAcknowledged THEN IF AcknowledgementRequired THEN diff --git a/src/core/ctrl/test/AxoMessaging/Static/AxoMessaging_UnitTests.st b/src/core/ctrl/test/AxoMessaging/Static/AxoMessaging_UnitTests.st index bc3f4eb22..01dbbd635 100644 --- a/src/core/ctrl/test/AxoMessaging/Static/AxoMessaging_UnitTests.st +++ b/src/core/ctrl/test/AxoMessaging/Static/AxoMessaging_UnitTests.st @@ -1389,6 +1389,247 @@ NAMESPACE AXOpen.AxoMessagingStatic_UnitTests _suti._object._messenger.ActivateOnCondition(UINT#1,FALSE,expMessage.Category).RequireAcknowledgement(); _suti.Close(); END_METHOD + + // ========== MESSAGE REQUALIFICATION TESTS ========== + + {Test} + METHOD PUBLIC potential_message_should_be_requalified_to_warning + VAR + expectedRisen : LDATE_AND_TIME; + END_VAR + //--Arrange + _suti.InjectMessengerService(_serviceSpy); + _serviceSpy.RequalifyDownstreamMessages(eAxoMessageCategory#Warning); + expectedRisen := LDATE_AND_TIME#2023-01-12-17:58:12.123; + _rtc.SetNowUTC(expectedRisen); + _suti.InjectRtc(_rtc); + + //--Act + _suti.Open(); + _suti.InitializeRootObject(_suti._object); + _suti._object._messenger.Serve(_suti._object); + _suti._object._messenger.Activate(UINT#1, eAxoMessageCategory#Potential); + _suti.Close(); + + //--Assert + Assert.Equal(TRUE, _suti._object._messenger.Category = eAxoMessageCategory#Warning); + Assert.Equal(TRUE, _suti._object._messenger.MessageCode = UINT#1); + Assert.Equal(TRUE, THIS.AreEqual(_suti._object._messenger.Risen, expectedRisen)); + Assert.Equal(TRUE, THIS.AreEqual(_suti._object._messenger.Fallen, LDATE_AND_TIME#1970-01-01-00:00:00.000)); + Assert.Equal(TRUE, THIS.AreEqual(_suti._object._messenger.Acknowledged, LDATE_AND_TIME#1970-01-01-00:00:00.000)); + END_METHOD + + {Test} + METHOD PUBLIC potential_message_should_be_requalified_to_error + VAR + expectedRisen : LDATE_AND_TIME; + END_VAR + //--Arrange + _suti.InjectMessengerService(_serviceSpy); + _serviceSpy.RequalifyDownstreamMessages(eAxoMessageCategory#Error); + expectedRisen := LDATE_AND_TIME#2023-01-12-17:58:12.123; + _rtc.SetNowUTC(expectedRisen); + _suti.InjectRtc(_rtc); + + //--Act + _suti.Open(); + _suti.InitializeRootObject(_suti._object); + _suti._object._messenger.Serve(_suti._object); + _suti._object._messenger.Activate(UINT#1, eAxoMessageCategory#Potential); + _suti.Close(); + + //--Assert + Assert.Equal(TRUE, _suti._object._messenger.Category = eAxoMessageCategory#Error); + Assert.Equal(TRUE, _suti._object._messenger.MessageCode = UINT#1); + Assert.Equal(TRUE, THIS.AreEqual(_suti._object._messenger.Risen, expectedRisen)); + END_METHOD + + {Test} + METHOD PUBLIC info_message_should_not_be_requalified + //--Arrange + _suti.InjectMessengerService(_serviceSpy); + _serviceSpy.RequalifyDownstreamMessages(eAxoMessageCategory#Error); + + //--Act + _suti.Open(); + _suti.InitializeRootObject(_suti._object); + _suti._object._messenger.Serve(_suti._object); + _suti._object._messenger.Activate(UINT#1, eAxoMessageCategory#Info); + _suti.Close(); + + //--Assert + Assert.Equal(TRUE, _suti._object._messenger.Category = eAxoMessageCategory#Info); + END_METHOD + + {Test} + METHOD PUBLIC warning_message_should_not_be_requalified + //--Arrange + _suti.InjectMessengerService(_serviceSpy); + _serviceSpy.RequalifyDownstreamMessages(eAxoMessageCategory#Error); + + //--Act + _suti.Open(); + _suti.InitializeRootObject(_suti._object); + _suti._object._messenger.Serve(_suti._object); + _suti._object._messenger.Activate(UINT#1, eAxoMessageCategory#Warning); + _suti.Close(); + + //--Assert + Assert.Equal(TRUE, _suti._object._messenger.Category = eAxoMessageCategory#Warning); + END_METHOD + + {Test} + METHOD PUBLIC error_message_should_not_be_requalified + //--Arrange + _suti.InjectMessengerService(_serviceSpy); + _serviceSpy.RequalifyDownstreamMessages(eAxoMessageCategory#Warning); + + //--Act + _suti.Open(); + _suti.InitializeRootObject(_suti._object); + _suti._object._messenger.Serve(_suti._object); + _suti._object._messenger.Activate(UINT#1, eAxoMessageCategory#Error); + _suti.Close(); + + //--Assert + Assert.Equal(TRUE, _suti._object._messenger.Category = eAxoMessageCategory#Error); + END_METHOD + + {Test} + METHOD PUBLIC critical_message_should_not_be_requalified + //--Arrange + _suti.InjectMessengerService(_serviceSpy); + _serviceSpy.RequalifyDownstreamMessages(eAxoMessageCategory#Error); + + //--Act + _suti.Open(); + _suti.InitializeRootObject(_suti._object); + _suti._object._messenger.Serve(_suti._object); + _suti._object._messenger.Activate(UINT#1, eAxoMessageCategory#Critical); + _suti.Close(); + + //--Assert + Assert.Equal(TRUE, _suti._object._messenger.Category = eAxoMessageCategory#Critical); + END_METHOD + + {Test} + METHOD PUBLIC requalification_should_happen_only_once + //--Arrange + _suti.InjectMessengerService(_serviceSpy); + _serviceSpy.RequalifyDownstreamMessages(eAxoMessageCategory#Warning); + + //--Act - First activation + _suti.Open(); + _suti.InitializeRootObject(_suti._object); + _suti._object._messenger.Serve(_suti._object); + _suti._object._messenger.Activate(UINT#1, eAxoMessageCategory#Potential); + _suti.Close(); + + //--Assert after first activation + Assert.Equal(TRUE, _suti._object._messenger.Category = eAxoMessageCategory#Warning); + + //--Act - Second activation with same message code + _suti.Open(); + _suti._object._messenger.Serve(_suti._object); + _serviceSpy.RequalifyDownstreamMessages(eAxoMessageCategory#Error); // Change requalification to Error + _suti._object._messenger.Activate(UINT#1, eAxoMessageCategory#Potential); + _suti.Close(); + + //--Assert after second activation - should remain Warning, not change to Error + Assert.Equal(TRUE, _suti._object._messenger.Category = eAxoMessageCategory#Warning); + END_METHOD + + {Test} + METHOD PUBLIC requalification_should_not_happen_when_service_is_not_configured_to_requalify + //--Arrange + _suti.InjectMessengerService(_serviceSpy); + _serviceSpy.RequalifyDownstreamMessages(eAxoMessageCategory#None); + + //--Act + _suti.Open(); + _suti.InitializeRootObject(_suti._object); + _suti._object._messenger.Serve(_suti._object); + _suti._object._messenger.Activate(UINT#1, eAxoMessageCategory#Potential); + _suti.Close(); + + //--Assert + Assert.Equal(TRUE, _suti._object._messenger.Category = eAxoMessageCategory#Potential); + END_METHOD + + {Test} + METHOD PUBLIC requalified_message_should_remain_active + //--Arrange + _suti.InjectMessengerService(_serviceSpy); + _serviceSpy.RequalifyDownstreamMessages(eAxoMessageCategory#Error); + + //--Act + _suti.Open(); + _suti.InitializeRootObject(_suti._object); + _suti._object._messenger.Serve(_suti._object); + _suti._object._messenger.Activate(UINT#1, eAxoMessageCategory#Potential); + _suti.Close(); + + //--Assert + Assert.Equal(TRUE, _suti._object._messenger.IsActive()); + Assert.Equal(TRUE, _suti._object._messenger.Category = eAxoMessageCategory#Error); + END_METHOD + + {Test} + METHOD PUBLIC requalification_should_preserve_message_code + VAR + messageCode : ULINT; + END_VAR + //--Arrange + _suti.InjectMessengerService(_serviceSpy); + _serviceSpy.RequalifyDownstreamMessages(eAxoMessageCategory#Warning); + messageCode := ULINT#12345; + + //--Act + _suti.Open(); + _suti.InitializeRootObject(_suti._object); + _suti._object._messenger.Serve(_suti._object); + _suti._object._messenger.Activate(messageCode, eAxoMessageCategory#Potential); + _suti.Close(); + + //--Assert + Assert.Equal(TRUE, _suti._object._messenger.MessageCode = messageCode); + Assert.Equal(TRUE, _suti._object._messenger.Category = eAxoMessageCategory#Warning); + END_METHOD + + {Test} + METHOD PUBLIC requalified_potential_to_warning_should_log_correctly + //--Arrange + _suti.InjectMessengerService(_serviceSpy); + _serviceSpy.RequalifyDownstreamMessages(eAxoMessageCategory#Warning); + + //--Act + _suti.Open(); + _suti.InitializeRootObject(_suti._object); + _suti._object._messenger.Serve(_suti._object); + _suti._object._messenger.Activate(UINT#1, eAxoMessageCategory#Potential); + _suti.Close(); + + //--Assert + Assert.Equal(TRUE, _suti._object._messenger.Category = eAxoMessageCategory#Warning); + Assert.Equal(TRUE, _suti._object._messenger.IsActive()); + END_METHOD + + {Test} + METHOD PUBLIC requalified_potential_to_error_should_require_acknowledgement + //--Arrange + _suti.InjectMessengerService(_serviceSpy); + _serviceSpy.RequalifyDownstreamMessages(eAxoMessageCategory#Error); + + //--Act + _suti.Open(); + _suti.InitializeRootObject(_suti._object); + _suti._object._messenger.Serve(_suti._object); + _suti._object._messenger.Activate(UINT#1, eAxoMessageCategory#Potential); + _suti.Close(); + + //--Assert + Assert.Equal(TRUE, _suti._object._messenger.Category = eAxoMessageCategory#Error); + END_METHOD END_CLASS END_NAMESPACE From 339da62d4b5a7a12d495b580c69769252989a562 Mon Sep 17 00:00:00 2001 From: Peter Kurhajec <61538034+PTKu@users.noreply.github.com> Date: Tue, 3 Mar 2026 16:26:33 +0100 Subject: [PATCH 09/13] Refactor logging conditions in AxoCylinder and enhance localization resources for multiple languages --- .../ctrl/src/AxoCylinder.st | 2 +- .../Properties/AxOpenCoreResources.de.resx | 84 +++++++++++++++++++ .../Properties/AxOpenCoreResources.es.resx | 84 +++++++++++++++++++ .../Properties/AxOpenCoreResources.sk.resx | 84 +++++++++++++++++++ .../Resources/PlcStringResources.de-DE.resx | 24 ++++++ .../Resources/PlcStringResources.de.resx | 9 ++ .../Resources/PlcStringResources.es-ES.resx | 24 ++++++ .../Resources/PlcStringResources.es.resx | 9 ++ .../Resources/PlcStringResources.hu-HU.resx | 24 ++++++ .../Resources/PlcStringResources.pl-PL.resx | 24 ++++++ .../Resources/PlcStringResources.sk.resx | 9 ++ 11 files changed, 376 insertions(+), 1 deletion(-) diff --git a/src/components.pneumatics/ctrl/src/AxoCylinder.st b/src/components.pneumatics/ctrl/src/AxoCylinder.st index 098d3795a..4bce6fa32 100644 --- a/src/components.pneumatics/ctrl/src/AxoCylinder.st +++ b/src/components.pneumatics/ctrl/src/AxoCylinder.st @@ -136,7 +136,7 @@ NAMESPACE AXOpen.Components.Pneumatics _MoveToOutIsBusy := _MoveOutTask.IsBusy(); - _Messenger.ActivateOnCondition(UINT#1, (_MoveToOutIsBusy AND NOT _MoveToOutIsSuspended AND _MoveOutTask.Duration >= T#10S), eAxoMessageCategory#Potential); + _Messenger.ActivateOnCondition(UINT#1, (_MoveToOutIsBusy AND NOT _MoveToOutIsSuspended), eAxoMessageCategory#Potential); _Messenger.ActivateOnCondition(UINT#9, (_MoveOutTask.IsDone() AND NOT _OutSensor), eAxoMessageCategory#Potential); diff --git a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.de.resx b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.de.resx index f0d2f23ce..279c9f59e 100644 --- a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.de.resx +++ b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.de.resx @@ -171,4 +171,88 @@ aktiv + + Fehler + + + Systemfehler + + + Schweregrad + + + Titel + + + Staat + + + Aktionen + + + Alarme suchen + + + Titel oder Ausrüstung suchen + + + Auffrischen + + + Meldungen aktualisieren + + + Es werden keine Alarme angezeigt. + + + Details ausblenden + + + Details anzeigen + + + Alarm quittieren + + + ACKN + + + Ack + + + Anhängig + + + Aktiv - Ack + + + Alarme + + + Alarm + + + Dienstansicht umschalten + + + Normal + + + Dienst + + + KONFIGURATION + + + STAAT + + + Daten + + + Schweregrad + + + Alarm-Code + \ No newline at end of file diff --git a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.es.resx b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.es.resx index b291e8dfc..96d4fe46c 100644 --- a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.es.resx +++ b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.es.resx @@ -171,4 +171,88 @@ activo + + Error + + + Error del sistema + + + Gravedad + + + Título + + + Estado + + + Acciones + + + Buscar alarmas + + + Buscar título o equipo + + + Actualizar + + + Actualizar mensajes + + + No hay alarmas que mostrar. + + + Ocultar detalles + + + Mostrar detalles + + + Confirmar alarma + + + ACKN + + + Ack + + + Pendiente + + + Activo - Ack + + + alarmas + + + alarma + + + Alternar vista de servicio + + + Normal + + + Servicio + + + CONFIGURACIÓN + + + ESTADO + + + Datos + + + Gravedad + + + Código de alarma + \ No newline at end of file diff --git a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.sk.resx b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.sk.resx index fc219282a..6bc6b9d08 100644 --- a/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.sk.resx +++ b/src/core/src/AXOpen.Core.Blazor/Properties/AxOpenCoreResources.sk.resx @@ -171,4 +171,88 @@ aktívny + + Chyba + + + Chyba systému + + + Závažnosť + + + Názov + + + Štát + + + Činnosti + + + Vyhľadávanie alarmov + + + Vyhľadávanie názvu alebo zariadenia + + + Obnoviť + + + Obnovenie správ + + + Nezobrazujú sa žiadne alarmy. + + + Skryť podrobnosti + + + Zobraziť podrobnosti + + + Potvrdenie alarmu + + + ACKN + + + Ack + + + Čaká sa na + + + Aktívne - Ack + + + alarmy + + + alarm + + + Prepnutie zobrazenia služby + + + Normálne + + + Služba + + + KONFIGURÁCIA + + + ŠTÁT + + + Údaje + + + Závažnosť + + + Kód alarmu + \ No newline at end of file diff --git a/src/core/src/AXOpen.Core/Resources/PlcStringResources.de-DE.resx b/src/core/src/AXOpen.Core/Resources/PlcStringResources.de-DE.resx index 390626be9..9e8c0113e 100644 --- a/src/core/src/AXOpen.Core/Resources/PlcStringResources.de-DE.resx +++ b/src/core/src/AXOpen.Core/Resources/PlcStringResources.de-DE.resx @@ -118,4 +118,28 @@ Gefallen + + Ist manuell steuerbar + + + Messenger 1 - Aktivierung mit der Methode "Activate", die innerhalb der if-Anweisung aufgerufen wird + + + RemoteTaskMessenger + + + Bote + + + Befehlsstatus + + + Schrittweiser Betrieb + + + Sequenz-Modus + + + Schritt ausführen + \ No newline at end of file diff --git a/src/core/src/AXOpen.Core/Resources/PlcStringResources.de.resx b/src/core/src/AXOpen.Core/Resources/PlcStringResources.de.resx index 801b17917..355b32082 100644 --- a/src/core/src/AXOpen.Core/Resources/PlcStringResources.de.resx +++ b/src/core/src/AXOpen.Core/Resources/PlcStringResources.de.resx @@ -192,4 +192,13 @@ Gefallen + + Messenger 1 - Aktivierung mit der Methode "Activate", die innerhalb der if-Anweisung aufgerufen wird + + + RemoteTaskMessenger + + + Bote + \ No newline at end of file diff --git a/src/core/src/AXOpen.Core/Resources/PlcStringResources.es-ES.resx b/src/core/src/AXOpen.Core/Resources/PlcStringResources.es-ES.resx index 2741f1283..579fe37bf 100644 --- a/src/core/src/AXOpen.Core/Resources/PlcStringResources.es-ES.resx +++ b/src/core/src/AXOpen.Core/Resources/PlcStringResources.es-ES.resx @@ -118,4 +118,28 @@ Caídos + + Se puede controlar manualmente + + + Mensajero 1 - activar usando el método 'Activate' llamado dentro de la sentencia if + + + RemoteTaskMessenger + + + Mensajero + + + Estado de mando + + + Modo escalonado + + + Modo secuencia + + + Ejecutar paso + \ No newline at end of file diff --git a/src/core/src/AXOpen.Core/Resources/PlcStringResources.es.resx b/src/core/src/AXOpen.Core/Resources/PlcStringResources.es.resx index 7aa7c3a27..4fbdd491b 100644 --- a/src/core/src/AXOpen.Core/Resources/PlcStringResources.es.resx +++ b/src/core/src/AXOpen.Core/Resources/PlcStringResources.es.resx @@ -192,4 +192,13 @@ Caídos + + Mensajero 1 - activar usando el método 'Activate' llamado dentro de la sentencia if + + + RemoteTaskMessenger + + + Mensajero + \ No newline at end of file diff --git a/src/core/src/AXOpen.Core/Resources/PlcStringResources.hu-HU.resx b/src/core/src/AXOpen.Core/Resources/PlcStringResources.hu-HU.resx index e96f90876..6d6ed328e 100644 --- a/src/core/src/AXOpen.Core/Resources/PlcStringResources.hu-HU.resx +++ b/src/core/src/AXOpen.Core/Resources/PlcStringResources.hu-HU.resx @@ -118,4 +118,28 @@ Fallen + + Kézi vezérlésű + + + Messenger 1 - aktiválás az if utasításon belül meghívott 'Activate' módszerrel + + + RemoteTaskMessenger + + + Messenger + + + Parancsállapot + + + Lépcső üzemmód + + + Szekvencia üzemmód + + + Futtatási lépés + \ No newline at end of file diff --git a/src/core/src/AXOpen.Core/Resources/PlcStringResources.pl-PL.resx b/src/core/src/AXOpen.Core/Resources/PlcStringResources.pl-PL.resx index 637617c75..3dd5873ca 100644 --- a/src/core/src/AXOpen.Core/Resources/PlcStringResources.pl-PL.resx +++ b/src/core/src/AXOpen.Core/Resources/PlcStringResources.pl-PL.resx @@ -118,4 +118,28 @@ Upadły + + Możliwość sterowania ręcznego + + + Messenger 1 - aktywacja przy użyciu metody "Activate" wywołanej wewnątrz instrukcji if + + + RemoteTaskMessenger + + + Posłaniec + + + Stan polecenia + + + Tryb krokowy + + + Tryb sekwencji + + + Krok działania + \ No newline at end of file diff --git a/src/core/src/AXOpen.Core/Resources/PlcStringResources.sk.resx b/src/core/src/AXOpen.Core/Resources/PlcStringResources.sk.resx index 58c837d61..d6cc36784 100644 --- a/src/core/src/AXOpen.Core/Resources/PlcStringResources.sk.resx +++ b/src/core/src/AXOpen.Core/Resources/PlcStringResources.sk.resx @@ -192,4 +192,13 @@ Fallen + + Messenger 1 - aktivácia pomocou metódy 'Activate' volanej vo vnútri príkazu if + + + RemoteTaskMessenger + + + Messenger + \ No newline at end of file From 7dc603db564c1910ed992f23a0a41deb100fbc97 Mon Sep 17 00:00:00 2001 From: Peter Kurhajec <61538034+PTKu@users.noreply.github.com> Date: Tue, 3 Mar 2026 17:00:08 +0100 Subject: [PATCH 10/13] Update Siemens.Simatic.S7.Webserver.API package version to 3.3.24 --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 27a94aace..06503b581 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -40,7 +40,7 @@ - + From 2fe3b585f7e9c9f07c67780c14f48ba62da40ab8 Mon Sep 17 00:00:00 2001 From: Peter Kurhajec <61538034+PTKu@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:55:04 +0100 Subject: [PATCH 11/13] Move message category enumeration to abstactions and enhance logging methods in AxoMessenger and related components Add various fixies related to messaging in components.pneumatics. --- .../src/AxoMessenger}/eAxoMessageCategory.st | 0 src/components.elements/ctrl/test/Mock.st | 11 +++ .../ctrl/src/AxoCylinder.st | 13 +-- .../ctrl/test/CylinderTests.st | 20 +++-- .../src/AxoMessaging/Static/AxoMessenger.st | 18 ++++- src/timers/ctrl/test/Abstractions.st | 11 +++ src/traversals/apax/apax.yml | 81 ------------------- 7 files changed, 58 insertions(+), 96 deletions(-) rename src/{core/ctrl/src/AxoMessaging => abstractions/ctrl/src/AxoMessenger}/eAxoMessageCategory.st (100%) delete mode 100644 src/traversals/apax/apax.yml diff --git a/src/core/ctrl/src/AxoMessaging/eAxoMessageCategory.st b/src/abstractions/ctrl/src/AxoMessenger/eAxoMessageCategory.st similarity index 100% rename from src/core/ctrl/src/AxoMessaging/eAxoMessageCategory.st rename to src/abstractions/ctrl/src/AxoMessenger/eAxoMessageCategory.st diff --git a/src/components.elements/ctrl/test/Mock.st b/src/components.elements/ctrl/test/Mock.st index f9100040d..731815b1b 100644 --- a/src/components.elements/ctrl/test/Mock.st +++ b/src/components.elements/ctrl/test/Mock.st @@ -67,5 +67,16 @@ NAMESPACE AXOpen.Components.Elements.Tests END_VAR ; END_METHOD + + METHOD PUBLIC Log + VAR_INPUT + _message : STRING[80]; + _level : eLogLevel; + _sender : IAxoObject; + _messageCode : ULINT; + END_VAR + + ; + END_METHOD END_CLASS END_NAMESPACE diff --git a/src/components.pneumatics/ctrl/src/AxoCylinder.st b/src/components.pneumatics/ctrl/src/AxoCylinder.st index 4bce6fa32..8c7b4fb61 100644 --- a/src/components.pneumatics/ctrl/src/AxoCylinder.st +++ b/src/components.pneumatics/ctrl/src/AxoCylinder.st @@ -136,9 +136,10 @@ NAMESPACE AXOpen.Components.Pneumatics _MoveToOutIsBusy := _MoveOutTask.IsBusy(); - _Messenger.ActivateOnCondition(UINT#1, (_MoveToOutIsBusy AND NOT _MoveToOutIsSuspended), eAxoMessageCategory#Potential); - _Messenger.ActivateOnCondition(UINT#9, (_MoveOutTask.IsDone() AND NOT _OutSensor), eAxoMessageCategory#Potential); - + IF(NOT _MoveToOutIsSuspended AND NOT THIS._MoveOutTask.IsDisabled) THEN + _Messenger.ActivateOnCondition(UINT#1, (_MoveToOutIsBusy AND NOT _MoveToOutIsSuspended), eAxoMessageCategory#Potential); + _Messenger.ActivateOnCondition(UINT#9, (_MoveOutTask.IsDone() AND NOT _OutSensor), eAxoMessageCategory#Potential); + END_IF; IF(_MoveInTask.Execute(THIS)) THEN IF(_MoveInTask.IsFirstExecutionCycle()) THEN @@ -151,8 +152,10 @@ NAMESPACE AXOpen.Components.Pneumatics _MoveToInIsBusy := _MoveInTask.IsBusy(); - _Messenger.ActivateOnCondition(UINT#2, (_MoveToInIsBusy AND NOT _MoveToInIsSuspended), eAxoMessageCategory#Potential); - _Messenger.ActivateOnCondition(UINT#8, (_MoveInTask.IsDone() AND NOT _InSensor), eAxoMessageCategory#Potential); + IF(NOT _MoveToInIsSuspended AND NOT THIS._MoveInTask.IsDisabled) THEN + _Messenger.ActivateOnCondition(UINT#2, (_MoveToInIsBusy AND NOT _MoveToInIsSuspended), eAxoMessageCategory#Potential); + _Messenger.ActivateOnCondition(UINT#8, (_MoveInTask.IsDone() AND NOT _InSensor), eAxoMessageCategory#Potential); + END_IF; outMoveInSignal := _MoveInSignal AND NOT _MoveToInIsSuspended; diff --git a/src/components.pneumatics/ctrl/test/CylinderTests.st b/src/components.pneumatics/ctrl/test/CylinderTests.st index 44c9a8258..b4fd2d468 100644 --- a/src/components.pneumatics/ctrl/test/CylinderTests.st +++ b/src/components.pneumatics/ctrl/test/CylinderTests.st @@ -205,7 +205,7 @@ NAMESPACE Cylinder.Tests AxUnit.Assert.Equal(TRUE, cylinder._MoveOutTask.IsBusy()); AxUnit.Assert.Equal(TRUE, cylinder.MoveOut().IsBusy()); // AxUnit.Assert.Equal(FALSE, cylinder._Messenger.IsActive); - AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); + AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessageCode = ULINT#4 && cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); context.Open(); context.InitializeRootObject(cylinderParent); @@ -240,7 +240,7 @@ NAMESPACE Cylinder.Tests AxUnit.Assert.Equal(TRUE, cylinder._MoveOutTask.IsBusy()); AxUnit.Assert.Equal(TRUE, cylinder.MoveOut().IsBusy()); // AxUnit.Assert.Equal(FALSE, cylinder._Messenger.IsActive); - AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); + AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessageCode = ULINT#4 && cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); context.Open(); _homeSensor := FALSE; @@ -278,7 +278,7 @@ NAMESPACE Cylinder.Tests AxUnit.Assert.Equal(TRUE, cylinder._MoveInTask.IsBusy()); AxUnit.Assert.Equal(TRUE, cylinder.MoveIn().IsBusy()); // AxUnit.Assert.Equal(FALSE, cylinder._Messenger.IsActive); - AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); + AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessageCode = ULINT#5 && cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); context.Open(); cylinder.SuspendMoveToInWhile(TRUE); @@ -313,7 +313,7 @@ NAMESPACE Cylinder.Tests AxUnit.Assert.Equal(TRUE, cylinder._MoveInTask.IsBusy()); AxUnit.Assert.Equal(TRUE, cylinder.MoveIn().IsBusy()); // AxUnit.Assert.Equal(FALSE, cylinder._Messenger.IsActive); - AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); + AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessageCode = ULINT#5 && cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); context.Open(); context.InitializeRootObject(cylinderParent); cylinder.SuspendMoveToInWhile(TRUE); @@ -419,6 +419,7 @@ NAMESPACE Cylinder.Tests AxUnit.Assert.Equal(FALSE, cylinder.MoveInSignal); AxUnit.Assert.Equal(TRUE, cylinder._MoveOutTask.IsBusy()); AxUnit.Assert.Equal(TRUE, cylinder.MoveOut().IsBusy()); + AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessageCode = ULINT#6 && cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); context.Open(); cylinder.AbortMoveToWorkWhen(TRUE); @@ -432,7 +433,7 @@ NAMESPACE Cylinder.Tests AxUnit.Assert.Equal(FALSE, cylinder.MoveOut().IsBusy()); // AxUnit.Assert.Equal(TRUE, cylinder._Messenger.IsActive); AxUnit.Assert.Equal(TRUE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); - AxUnit.Assert.Equal(TRUE,THIS.AreEqual(dt, cylinder._Messenger.Risen)); + AxUnit.Assert.Equal(cylinder._Messenger.MessageCode, ULINT#6); END_METHOD {Test} @@ -453,7 +454,7 @@ NAMESPACE Cylinder.Tests AxUnit.Assert.Equal(TRUE, cylinder._MoveOutTask.IsBusy()); AxUnit.Assert.Equal(TRUE, cylinder.MoveOut().IsBusy()); // AxUnit.Assert.Equal(FALSE, cylinder._Messenger.IsActive); - AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); + AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessageCode = ULINT#6 && cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); context.Open(); context.InitializeRootObject(cylinderParent); @@ -467,6 +468,7 @@ NAMESPACE Cylinder.Tests AxUnit.Assert.Equal(FALSE, cylinder.MoveOut().IsBusy()); // AxUnit.Assert.Equal(TRUE, cylinder._Messenger.IsActive); AxUnit.Assert.Equal(TRUE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); + AxUnit.Assert.Equal(cylinder._Messenger.MessageCode, ULINT#6); AxUnit.Assert.Equal(TRUE,THIS.AreEqual(dt, cylinder._Messenger.Risen)); END_METHOD @@ -488,7 +490,7 @@ NAMESPACE Cylinder.Tests AxUnit.Assert.Equal(TRUE, cylinder._MoveInTask.IsBusy()); AxUnit.Assert.Equal(TRUE, cylinder.MoveIn().IsBusy()); // AxUnit.Assert.Equal(FALSE, cylinder._Messenger.IsActive); - AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); + AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessageCode = ULINT#7 && cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); context.Open(); cylinder.AbortMoveToHomeWhen(TRUE); @@ -502,6 +504,7 @@ NAMESPACE Cylinder.Tests AxUnit.Assert.Equal(FALSE, cylinder.MoveIn().IsBusy()); // AxUnit.Assert.Equal(TRUE, cylinder._Messenger.IsActive); AxUnit.Assert.Equal(TRUE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); + AxUnit.Assert.Equal(cylinder._Messenger.MessageCode, ULINT#7); AxUnit.Assert.Equal(TRUE,THIS.AreEqual(dt, cylinder._Messenger.Risen)); END_METHOD @@ -523,7 +526,7 @@ NAMESPACE Cylinder.Tests AxUnit.Assert.Equal(TRUE, cylinder._MoveInTask.IsBusy()); AxUnit.Assert.Equal(TRUE, cylinder.MoveIn().IsBusy()); // AxUnit.Assert.Equal(FALSE, cylinder._Messenger.IsActive); - AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); + AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessageCode = ULINT#7 && cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); context.Open(); context.InitializeRootObject(cylinderParent); @@ -537,6 +540,7 @@ NAMESPACE Cylinder.Tests AxUnit.Assert.Equal(FALSE, cylinder.MoveIn().IsBusy()); // AxUnit.Assert.Equal(TRUE, cylinder._Messenger.IsActive); AxUnit.Assert.Equal(TRUE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired); + AxUnit.Assert.Equal(cylinder._Messenger.MessageCode, ULINT#7); AxUnit.Assert.Equal(TRUE,THIS.AreEqual(dt, cylinder._Messenger.Risen)); END_METHOD diff --git a/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st b/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st index e9bd02703..7555cfebb 100644 --- a/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st +++ b/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st @@ -128,7 +128,8 @@ NAMESPACE AXOpen.Messaging.Static // "Complete new" activation - IF THIS.MessengerState = eAxoMessengerState#Idle AND MessageCode = ULINT#0 AND ActiveContextCount = ULINT#0 THEN + IF THIS.MessengerState = eAxoMessengerState#Idle AND MessageCode = ULINT#0 + AND ActiveContextCount = ULINT#0 THEN Risen := _context.GetRtc().NowUTC(); Fallen := LDATE_AND_TIME#1970-01-01-00:00:00.000; Acknowledged := LDATE_AND_TIME#1970-01-01-00:00:00.000; @@ -138,7 +139,20 @@ NAMESPACE AXOpen.Messaging.Static _requalifiedToCategory := eAxoMessageCategory#None; // AcknowledgementRequired := Category >= eAxoMessageCategory#Error; END_IF; - + + // Activation with different message code without deactivation of the previous one. + // This can only happen with non-acknowledgeable messages, as acknowledgeable messages require deactivation or acknowledgement + // before being able to be activated again with a different message code. + IF THIS.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired && MessageCode <> _messageCode THEN + Risen := _context.GetRtc().NowUTC(); + Fallen := LDATE_AND_TIME#1970-01-01-00:00:00.000; + Acknowledged := LDATE_AND_TIME#1970-01-01-00:00:00.000; + _context.GetLogger().Log(RISE_SIGNATURE, THIS.ToLogLevel(_category), THIS, _messageCode); + MessageCode := _messageCode; + Category := _category; + _requalifiedToCategory := eAxoMessageCategory#None; + END_IF; + // "Reactivation" in case of acknowledgable alarm rised, falled and rised again without acknowledgement IF THIS.MessengerState = eAxoMessengerState#InactiveWaitingForAcknowledge AND MessageCode = _messageCode AND diff --git a/src/timers/ctrl/test/Abstractions.st b/src/timers/ctrl/test/Abstractions.st index 649697ee6..da807c659 100644 --- a/src/timers/ctrl/test/Abstractions.st +++ b/src/timers/ctrl/test/Abstractions.st @@ -34,6 +34,17 @@ NAMESPACE AXOpen.Timers_tests END_VAR ; END_METHOD + + METHOD PUBLIC Log + VAR_INPUT + _message : STRING[80]; + _level : eLogLevel; + _sender : IAxoObject; + _messageCode : ULINT; + END_VAR + + ; + END_METHOD END_CLASS {S7.extern=ReadWrite} diff --git a/src/traversals/apax/apax.yml b/src/traversals/apax/apax.yml deleted file mode 100644 index 35d99764d..000000000 --- a/src/traversals/apax/apax.yml +++ /dev/null @@ -1,81 +0,0 @@ -name: "apax.traversal" -version: "0.0.0-dev.0" -type: "app" -targets: -- "1500" -registries: - '@inxton': "https://npm.pkg.github.com/" -devDependencies: - '@inxton/ax-sdk': "0.0.0-dev.0" -dependencies: - "abstractions-app": "0.0.0-dev.0" - "@inxton/axopen.abstractions": "0.0.0-dev.0" - "@inxton/ax.axopen.app": "0.0.0-dev.0" - "@inxton/ax.axopen.hwlibrary": "0.0.0-dev.0" - "@inxton/ax.axopen.min": "0.0.0-dev.0" - "@inxton/ax.catalog": "0.0.46" - "app_axopen.components.abb.robotics": "0.0.0-dev.0" - "@inxton/axopen.components.abb.robotics": "0.0.0-dev.0" - "components.abstractions-app": "0.0.0-dev.0" - "@inxton/axopen.components.abstractions": "0.0.0-dev.0" - "app_axopen.components.balluff.identification": "0.0.0-dev.0" - "@inxton/axopen.components.balluff.identification": "0.0.0-dev.0" - "app_axopen.components.cognex.vision": "0.0.0-dev.0" - "@inxton/axopen.components.cognex.vision": "0.0.0-dev.0" - "app_axopen.components.desoutter.tightening": "0.0.0-dev.0" - "@inxton/axopen.components.desoutter.tightening": "0.0.0-dev.0" - "app_axopen.components.drives": "0.0.0-dev.0" - "@inxton/axopen.components.drives": "0.0.0-dev.0" - "app_axopen.components.dukane.welders": "0.0.0-dev.0" - "@inxton/axopen.components.dukane.welders": "0.0.0-dev.0" - "elementscomponents": "0.0.0-dev.0" - "@inxton/axopen.components.elements": "0.0.0-dev.0" - "app_axopen.components.festo.drives": "0.0.0-dev.0" - "@inxton/axopen.components.festo.drives": "0.0.0-dev.0" - "app_axopen.components.keyence.vision": "0.0.0-dev.0" - "@inxton/axopen.components.keyence.vision": "0.0.0-dev.0" - "app_axopen.components.kuka.robotics": "0.0.0-dev.0" - "@inxton/axopen.components.kuka.robotics": "0.0.0-dev.0" - "app_axopen.components.mitsubishi.robotics": "0.0.0-dev.0" - "@inxton/axopen.components.mitsubishi.robotics": "0.0.0-dev.0" - "pneumaticcomponents": "0.0.0-dev.0" - "@inxton/axopen.components.pneumatics": "0.0.0-dev.0" - "app_axopen.components.rexroth.drives": "0.0.0-dev.0" - "@inxton/axopen.components.rexroth.drives": "0.0.0-dev.0" - "app_axopen.components.rexroth.press": "0.0.0-dev.0" - "@inxton/axopen.components.rexroth.press": "0.0.0-dev.0" - "app_axopen.components.rexroth.tightening": "0.0.0-dev.0" - "@inxton/axopen.components.rexroth.tightening": "0.0.0-dev.0" - "app_axopen.components.robotics": "0.0.0-dev.0" - "@inxton/axopen.components.robotics": "0.0.0-dev.0" - "app_axopen.components.siem.communication": "0.0.0-dev.0" - "@inxton/axopen.components.siem.communication": "0.0.0-dev.0" - "app_axopen.components.siem.identification": "0.0.0-dev.0" - "@inxton/axopen.components.siem.identification": "0.0.0-dev.0" - "app_axopen.components.ur.robotics": "0.0.0-dev.0" - "@inxton/axopen.components.ur.robotics": "0.0.0-dev.0" - "app_axopen.components.zebra.vision": "0.0.0-dev.0" - "@inxton/axopen.components.zebra.vision": "0.0.0-dev.0" - "ix_axopencore": "0.0.0-dev.0" - "@inxton/axopen.core": "0.0.0-dev.0" - "axopen.data-app": "0.0.0-dev.0" - "@inxton/axopen.data": "0.0.0-dev.0" - "axopen.data.tests_l1": "0.0.0-dev.0" - "axopen.integration.tests_l4": "0.0.0-dev.0" - "axopen.inspectors": "0.0.0-dev.0" - "@inxton/axopen.inspectors": "0.0.0-dev.0" - "axopen.integrations": "0.0.0-dev.0" - "app_axopen.io": "0.0.0-dev.0" - "@inxton/axopen.io": "0.0.0-dev.0" - "probers-app": "0.0.0-dev.0" - "@inxton/axopen.probers": "0.0.0-dev.0" - "simatic1500-app": "0.0.0-dev.0" - "@inxton/axopen.simatic1500": "0.0.0-dev.0" - "app_apaxappname": "0.0.0-dev.0" - "@inxton/apaxlibname": "0.0.0-dev.0" - "timers-app": "0.0.0-dev.0" - "@inxton/axopen.timers": "0.0.0-dev.0" - "utils-app": "0.0.0-dev.0" - "@inxton/axopen.utils": "0.0.0-dev.0" -installStrategy: "overridable" -... From 9c56d1acceb3bd4d1fb511a2b6bee6125b3d5c51 Mon Sep 17 00:00:00 2001 From: Peter Kurhajec <61538034+PTKu@users.noreply.github.com> Date: Wed, 4 Mar 2026 16:13:46 +0100 Subject: [PATCH 12/13] Enhance AxoMessageProvider and Flattener to support observed depth for improved message handling --- .../AxoMessenger/Static/AxoMessageProvider.cs | 13 ++++++++----- src/toolbox/src/AXOpen.ToolBox/Flattener.cs | 13 ++++++++++++- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/core/src/AXOpen.Core/AxoMessenger/Static/AxoMessageProvider.cs b/src/core/src/AXOpen.Core/AxoMessenger/Static/AxoMessageProvider.cs index e5c9783cb..21988b4cb 100644 --- a/src/core/src/AXOpen.Core/AxoMessenger/Static/AxoMessageProvider.cs +++ b/src/core/src/AXOpen.Core/AxoMessenger/Static/AxoMessageProvider.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection.Metadata; @@ -16,12 +16,15 @@ namespace AXOpen.Messaging.Static ///
public class AxoMessageProvider { - private AxoMessageProvider(IEnumerable observedObjects) + private AxoMessageProvider(IEnumerable observedObjects, int observedDepth = int.MaxValue) { this.ObservedObjects = observedObjects; + this.ObservedDepth = observedDepth; } public IEnumerable ObservedObjects { get; } + + public int ObservedDepth { get; } private int? _cachedActiveMessagesCount; private int? _maxActiveMessagesCount; @@ -192,7 +195,7 @@ public AxoMessenger[]? Messengers var retVal = new List(); foreach (var observedObject in ObservedObjects.Where(p => p != null)) { - retVal.AddRange(observedObject.GetChildren().Flatten(p => p.GetChildren()) + retVal.AddRange(observedObject.GetChildren().Flatten(p => p.GetChildren(), this.ObservedDepth) .OfType()); } @@ -208,9 +211,9 @@ public AxoMessenger[]? Messengers /// /// The collection of observed objects. /// A new instance of the AxoMessageProvider class. - public static AxoMessageProvider Create(IEnumerable observedObjects) + public static AxoMessageProvider Create(IEnumerable observedObjects, int observedDepth = int.MaxValue) { - return new AxoMessageProvider(observedObjects); + return new AxoMessageProvider(observedObjects, observedDepth); } diff --git a/src/toolbox/src/AXOpen.ToolBox/Flattener.cs b/src/toolbox/src/AXOpen.ToolBox/Flattener.cs index 55d2a1b0b..1acce469f 100644 --- a/src/toolbox/src/AXOpen.ToolBox/Flattener.cs +++ b/src/toolbox/src/AXOpen.ToolBox/Flattener.cs @@ -9,10 +9,21 @@ public static class Flattener /// /// /// + /// Optional maximum depth for flattening. Defaults to no limit. /// public static IEnumerable Flatten( this IEnumerable e , Func> f - ) => e.SelectMany(c => f(c).Flatten(f)).Concat(e); + , int maxDepth = int.MaxValue + ) => FlattenCore(e, f, maxDepth, 0); + + private static IEnumerable FlattenCore( + IEnumerable e + , Func> f + , int maxDepth + , int depth + ) => depth < maxDepth + ? e.SelectMany(c => FlattenCore(f(c), f, maxDepth, depth + 1)).Concat(e) + : e; } } \ No newline at end of file From bbe991762ec411b4e87de6f00c004e0eaf5de39c Mon Sep 17 00:00:00 2001 From: Peter Kurhajec <61538034+PTKu@users.noreply.github.com> Date: Wed, 4 Mar 2026 16:46:32 +0100 Subject: [PATCH 13/13] Documentation updates --- CHANGELOG.md | 38 +++++++++++++++++++++++++ docfx/articles/guidelines/components.md | 24 ++++++++++++++++ src/core/docs/AXOLOGGER.md | 9 ++++-- src/core/docs/AXOMESSENGER.md | 14 +++++++-- 4 files changed, 81 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06f2eaf7d..d7af799ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,41 @@ +### [CORE] Controller logger updates ([#1054](https://github.com/Inxton/AXOpen/pull/1054)) + +**Note:** Enhanced logging and messaging capabilities with new message categories and requalification features. + +- feat: Added new `Potential` message category (severity level 150) for messages that may escalate to warnings or errors +- feat: Introduced message requalification system via `RequalifyDownstreamMessages()` to allow downstream message category promotion +- feat: Added `_messageCode` parameter to logger methods for improved message tracking and identification +- feat: Implemented step timeout detection in `AxoSequencer` with automatic error message generation +- feat: Enhanced `AxoMessageProvider` and `Flattener` to support configurable observation depth +- refactor: Standardized severity localization keys (simplified from "SeverityInfo" to "Info", etc.) +- refactor: Updated AxoMessenger logging signatures to use rise/fall signature markers for clarity +- chore: Bumped AXSharp packages to 0.47.0-alpha.452 and Siemens.Simatic.S7.Webserver.API to 3.3.24 + +**Impact:** +- Enables intermediate message categorization before escalation to warnings or errors +- Improves diagnostics through message code tracking and step timeout detection +- Provides better control over message severity in distributed systems +- Simplifies localization maintenance with consistent key naming + +**New Message Categories:** +- `None` (0): No category; ignore non-critical messages +- `Info` (100): Informative messages with minimal impact +- `Potential` (150): Potential problems that may escalate (automatically requalified if configured) +- `Warning` (200): Possible problems affecting the process +- `Error` (300): Failures requiring intervention +- `Critical` (400): Critical system failures +- `ProgrammingError` (500): Implementation/configuration errors + +**Risks/Review:** +- Existing code using old severity localization keys should be updated to use new simplified keys +- Message requalification logic should be tested in environments with coordinated components +- Step timeout thresholds should be validated for application-specific timing requirements + +**Testing:** +- Unit tests for message requalification across all categories +- Integration tests for step timeout scenarios in sequencers +- Localization verification for all supported languages + ### [INTEGRATIONS] Additional alignments with application template ([#768](https://github.com/Inxton/AXOpen/pull/768)) **Note:** Namespace and component renames require consumers to update imports, templates, and generated UI bindings before upgrading. diff --git a/docfx/articles/guidelines/components.md b/docfx/articles/guidelines/components.md index d0671c045..0a3e3cb89 100644 --- a/docfx/articles/guidelines/components.md +++ b/docfx/articles/guidelines/components.md @@ -123,6 +123,30 @@ Components should surface diagnostic and alarm information consistently: For UI auto‑rendering the alarm level icons provided by `AxoComponent` will reflect the highest active severity; ensure warnings are deactivated when condition clears to avoid stale visualization. +### Message Categories + +The framework supports the following message categories (in order of severity): + +* **None** (0): No category; used to clear requalification directives and ignore non-critical messages +* **Info** (100): Informative messages with minimal impact; do not require operator intervention +* **Potential** (150): Potential problems that may escalate to Warning or Error states; these messages can be automatically requalified based on system configuration when downstream conditions are detected +* **Warning** (200): Possible problems that may adversely affect a process; information to help identify problems but does not necessarily stop the process +* **Error** (300): Failures that cannot be immediately recovered; intervention is needed +* **Critical** (400): Critical system failures +* **ProgrammingError** (500): Implementation or configuration errors in the application + +When using the `Potential` category, ensure that the parent context or sequencer is configured with appropriate requalification rules to escalate potential issues to `Warning` or `Error` when conditions persist. + +### Message Requalification + +For coordinated components and sequencers, message requalification allows upstream components to influence downstream message severity. Use `GetMessengerService().RequalifyDownstreamMessages(category)` to set the requalification category. This is particularly useful for: + +* Escalating `Potential` messages to `Warning` or `Error` based on elapsed time +* Implementing hierarchical error response strategies in multi-step workflows +* Ensuring consistent severity handling across component hierarchies + +Note: Only `Potential` messages are subject to requalification; other categories retain their configured severity. + ## Documentation requirements diff --git a/src/core/docs/AXOLOGGER.md b/src/core/docs/AXOLOGGER.md index 2f80420ba..1217a8cc4 100644 --- a/src/core/docs/AXOLOGGER.md +++ b/src/core/docs/AXOLOGGER.md @@ -155,17 +155,22 @@ This example showcases how to initialize a logger in a .NET application using th --- ## AxoLogger and AxoMessenger -AxoMessenger uses Context AxoLogger to log the rising and falling of an alarm. There is no particular need for the configuration fo this behaviour. +AxoMessenger uses Context AxoLogger to log the rising and falling of an alarm. There is no particular need for the configuration of this behaviour. Here are the mappings between eAxoMessageCategory and eLogLevel as per the code: - Trace messages are logged as Verbose. - Debug messages are logged as Debug. -- Info, TimedOut, and Notification messages are logged as - Information. +- Info and Notification messages are logged as Information. +- **Potential messages are logged as Information** (These are potential problems that may escalate to Warning or Error based on system requalification configuration). - Warning messages are logged as Warning. - Error and ProgrammingError messages are logged as Error. - Critical, Fatal, and Catastrophic messages are logged as Fatal. +### Message Requalification and Logging + +When a `Potential` message is requalified by the downstream `AxoMessengerService` to a `Warning` or `Error` category, the log level will be updated accordingly at the requalification point. This allows for intermediate detection of issues that may escalate during execution of coordinated components and sequencers. + diff --git a/src/core/docs/AXOMESSENGER.md b/src/core/docs/AXOMESSENGER.md index 0a03ca30c..28c1d7faf 100644 --- a/src/core/docs/AXOMESSENGER.md +++ b/src/core/docs/AXOMESSENGER.md @@ -27,9 +27,19 @@ Static `AxoMessenger` is a class that provides a mechanism for delivering static Depending on the [eAxoMessageCategory](../../../docs/apictrl/abstractions/plc.AXOpen.Messaging.eAxoMessageCategory.html) the messenger should require the acknowledgement. -By default the acknowledgement is not required for the levels `Trace`,`Debug`,`Info`,`TimedOut`,`Notification` and `Warning`. +By default the acknowledgement is not required for the levels `Trace`, `Debug`, `Info`, `Notification`, `Potential` and `Warning`. This could be overwritten by calling the `RequireAcknowledgement()` method. -Contrariwise, the acknowledgement is required for the levels `Error`,`ProgrammingError`,`Critical`,`Fatal` and `Catastrophic` by default. This could be overwritten by calling the `DoNotRequireAcknowledgement()` method. +Contrariwise, the acknowledgement is required for the levels `Error`, `ProgrammingError`, `Critical`, `Fatal` and `Catastrophic` by default. This could be overwritten by calling the `DoNotRequireAcknowledgement()` method. + +### Potential Message Category and Requalification + +The `Potential` message category (severity level 150) represents potential problems that may escalate to `Warning` or `Error` states depending on system configuration. This category is useful for: + +- Identifying emerging issues that may require escalation +- Implementing hierarchical error handling in complex workflows +- Allowing downstream components to determine severity based on context + +A `Potential` message can be automatically requalified to `Warning` or `Error` by configuring the messenger service through the `RequalifyDownstreamMessages(category)` method. This is particularly useful in sequencers and multi-step processes where conditions may escalate over time (e.g., a step taking longer than expected may be initially reported as `Potential` and then escalated to `Error` if it exceeds the configured time threshold). **Attributes `MessageText`, `Help` and `PlcTextList`**