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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"AXSharp.ixc": {
"version": "0.47.0-alpha.452",
"version": "0.47.0-alpha.439",
"commands": [
"ixc"
],
Expand All @@ -17,14 +17,14 @@
"rollForward": false
},
"AXSharp.ixd": {
"version": "0.47.0-alpha.452",
"version": "0.47.0-alpha.439",
"commands": [
"ixd"
],
"rollForward": false
},
"AXSharp.ixr": {
"version": "0.47.0-alpha.452",
"version": "0.47.0-alpha.439",
"commands": [
"ixr"
],
Expand Down
38 changes: 0 additions & 38 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,3 @@
### [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.
Expand Down
12 changes: 6 additions & 6 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
<!-- Framework-Agnostic Packages -->
<ItemGroup>
<!-- AX# Libraries -->
<PackageVersion Include="AXSharp.Abstractions" Version="0.47.0-alpha.452" />
<PackageVersion Include="AXSharp.Connector" Version="0.47.0-alpha.452" />
<PackageVersion Include="AXSharp.Connector.S71500.WebAPI" Version="0.47.0-alpha.452" />
<PackageVersion Include="AXSharp.Presentation.Blazor" Version="0.47.0-alpha.452" />
<PackageVersion Include="AXSharp.Presentation.Blazor.Controls" Version="0.47.0-alpha.452" />
<PackageVersion Include="AXSharp.Abstractions" Version="0.47.0-alpha.439" />
<PackageVersion Include="AXSharp.Connector" Version="0.47.0-alpha.439" />
<PackageVersion Include="AXSharp.Connector.S71500.WebAPI" Version="0.47.0-alpha.439" />
<PackageVersion Include="AXSharp.Presentation.Blazor" Version="0.47.0-alpha.439" />
<PackageVersion Include="AXSharp.Presentation.Blazor.Controls" Version="0.47.0-alpha.439" />
<PackageVersion Include="Inxton.Operon" Version="0.3.0-alpha.114" />
<!-- Data & Serialization -->
<PackageVersion Include="ClosedXML" Version="0.105.0" />
Expand All @@ -40,7 +40,7 @@
<PackageVersion Include="Serilog" Version="4.3.0" />
<PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />
<!-- Hardware & Devices -->
<PackageVersion Include="Siemens.Simatic.S7.Webserver.API" Version="3.3.24" />
<PackageVersion Include="Siemens.Simatic.S7.Webserver.API" Version="3.3.3" />
<!-- Testing - Core -->
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageVersion Include="NSubstitute" Version="5.3.0" />
Expand Down
24 changes: 0 additions & 24 deletions docfx/articles/guidelines/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,30 +123,6 @@ 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

Expand Down
7 changes: 1 addition & 6 deletions src/abstractions/ctrl/src/AxoLogger/IAxoLogger.st
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ NAMESPACE AXOpen.Logging
/// _message is a string of maximum 80 characters that represents the log message
/// </summary>
_message : STRING[80];

/// <summary>
/// _level is an instance of eLogLevel that represents the level of the log
/// </summary>
Expand All @@ -35,11 +35,6 @@ NAMESPACE AXOpen.Logging
/// _sender is an instance of IAxoObject that represents the sender of the log
/// </summary>
_sender : IAxoObject;

/// <summary>
/// _messageCode is an unsigned long integer that represents the code of the log message
/// </summary>
_messageCode : ULINT;
END_VAR
END_METHOD

Expand Down
29 changes: 0 additions & 29 deletions src/abstractions/ctrl/src/AxoMessenger/IAxoMessengerService.st
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,8 @@ NAMESPACE AXOpen.Core
inMessegenger : IAxoMessenger;
END_VAR
END_METHOD
/// <summary>
/// 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.
/// </summary>
METHOD SuspendMessaging END_METHOD

/// <summary>
/// Resumes the messaging system. When resumed, messages that arose while the system was suspended will NOT be sent to subscribers.
/// </summary>
METHOD ResumeMessaging END_METHOD

/// <summary>
/// Checks if the messaging system is currently suspended.
/// Returns true if the messaging system is suspended, false otherwise.
/// </summary>
METHOD IsSuspended : BOOL END_METHOD

/// <summary>
/// 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.
/// </summary>
METHOD RequalifyDownstreamMessages
VAR_INPUT
inMessageCategory : AXOpen.Messaging.eAxoMessageCategory;
END_VAR
END_METHOD

/// <summary>
/// Gets the requalified message category for downstream messages.
/// </summary>
METHOD GetRequalifiedMessageCategory : AXOpen.Messaging.eAxoMessageCategory END_METHOD
END_INTERFACE
END_NAMESPACE
11 changes: 0 additions & 11 deletions src/components.elements/ctrl/test/Mock.st
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,5 @@ 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
15 changes: 6 additions & 9 deletions src/components.pneumatics/ctrl/src/AxoCylinder.st
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ NAMESPACE AXOpen.Components.Pneumatics

_Messenger.Serve(THIS);

_Messenger.ActivateOnCondition(UINT#3, _OutSensor AND _InSensor, eAxoMessageCategory#Warning);
_Messenger.ActivateOnCondition(UINT#3, _OutSensor AND _InSensor, eAxoMessageCategory#Error);

IF(_StopTask.Execute(THIS)) THEN
_MoveInSignal := FALSE;
Expand All @@ -136,10 +136,9 @@ NAMESPACE AXOpen.Components.Pneumatics

_MoveToOutIsBusy := _MoveOutTask.IsBusy();

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;
_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);


IF(_MoveInTask.Execute(THIS)) THEN
IF(_MoveInTask.IsFirstExecutionCycle()) THEN
Expand All @@ -152,10 +151,8 @@ NAMESPACE AXOpen.Components.Pneumatics

_MoveToInIsBusy := _MoveInTask.IsBusy();

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;
_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);


outMoveInSignal := _MoveInSignal AND NOT _MoveToInIsSuspended;
Expand Down
20 changes: 8 additions & 12 deletions src/components.pneumatics/ctrl/test/CylinderTests.st
Original file line number Diff line number Diff line change
Expand Up @@ -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.MessageCode = ULINT#4 && cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired);
AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired);

context.Open();
context.InitializeRootObject(cylinderParent);
Expand Down Expand Up @@ -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.MessageCode = ULINT#4 && cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired);
AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired);

context.Open();
_homeSensor := FALSE;
Expand Down Expand Up @@ -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.MessageCode = ULINT#5 && cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired);
AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired);

context.Open();
cylinder.SuspendMoveToInWhile(TRUE);
Expand Down Expand Up @@ -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.MessageCode = ULINT#5 && cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired);
AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired);
context.Open();
context.InitializeRootObject(cylinderParent);
cylinder.SuspendMoveToInWhile(TRUE);
Expand Down Expand Up @@ -419,7 +419,6 @@ 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);
Expand All @@ -433,7 +432,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

{Test}
Expand All @@ -454,7 +453,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.MessageCode = ULINT#6 && cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired);
AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired);

context.Open();
context.InitializeRootObject(cylinderParent);
Expand All @@ -468,7 +467,6 @@ 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

Expand All @@ -490,7 +488,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.MessageCode = ULINT#7 && cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired);
AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired);

context.Open();
cylinder.AbortMoveToHomeWhen(TRUE);
Expand All @@ -504,7 +502,6 @@ 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

Expand All @@ -526,7 +523,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.MessageCode = ULINT#7 && cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired);
AxUnit.Assert.Equal(FALSE, cylinder._Messenger.MessengerState = eAxoMessengerState#ActiveAcknowledgeNotRequired);

context.Open();
context.InitializeRootObject(cylinderParent);
Expand All @@ -540,7 +537,6 @@ 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

Expand Down
Loading
Loading