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
60 changes: 50 additions & 10 deletions src/core/src/AXOpen.Core/AxoMessenger/Static/AxoMessageProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@ private AxoMessageProvider(IEnumerable<ITwinObject> observedObjects)
public IEnumerable<ITwinObject> ObservedObjects { get; }

private int? _cachedActiveMessagesCount;
private int? _maxActiveMessagesCount;
private DateTime _lastActiveMessagesCountUpdate = DateTime.MinValue;
private readonly TimeSpan _activeMessagesCountCacheDuration = TimeSpan.FromMilliseconds(500);
private DateTime _maxActiveMessagesCountSetTime = DateTime.MinValue;
private readonly TimeSpan _activeMessagesCountCacheDuration = TimeSpan.FromMilliseconds(100);
private readonly TimeSpan _maxValueHoldDuration = TimeSpan.FromSeconds(2);
private readonly object _activeMessagesCountLock = new object();

/// <summary>
Expand All @@ -34,7 +37,9 @@ private AxoMessageProvider(IEnumerable<ITwinObject> observedObjects)
/// <remarks>
/// This property counts the number of messages that are currently active.
/// An active message is defined as a message belonging to a Messenger that has a state other than Idle or NotActiveWatingAckn.
/// The value is cached for a short period to prevent flickering due to asynchronous PLC communication.
/// The value uses a maximum-tracking mechanism to prevent flickering caused by PLC cycle timing,
/// where the message count is accumulated during each controller cycle starting from 0.
/// The maximum value seen is held for a period since the correct full count persists longer than partial counts.
/// </remarks>
public int? ActiveMessagesCount
{
Expand All @@ -44,11 +49,11 @@ public int? ActiveMessagesCount
{
var now = DateTime.UtcNow;

// Return cached value if still valid
// Return cached value if we just read recently
if (_cachedActiveMessagesCount.HasValue &&
(now - _lastActiveMessagesCountUpdate) < _activeMessagesCountCacheDuration)
{
return _cachedActiveMessagesCount;
return _maxActiveMessagesCount ?? _cachedActiveMessagesCount;
}

try
Expand All @@ -61,7 +66,20 @@ public int? ActiveMessagesCount
_cachedActiveMessagesCount = count;
_lastActiveMessagesCountUpdate = now;

return count;
// Track maximum value seen
if (!_maxActiveMessagesCount.HasValue || count > _maxActiveMessagesCount.Value)
{
_maxActiveMessagesCount = count;
_maxActiveMessagesCountSetTime = now;
}
// Reset max if hold duration has passed and current value is lower
else if ((now - _maxActiveMessagesCountSetTime) > _maxValueHoldDuration)
{
_maxActiveMessagesCount = count;
_maxActiveMessagesCountSetTime = now;
}

return _maxActiveMessagesCount;
}
catch (Exception e)
{
Expand All @@ -73,8 +91,11 @@ public int? ActiveMessagesCount


private int? _cachedRelevantMessagesCount;
private int? _maxRelevantMessagesCount;
private DateTime _lastRelevantMessagesCountUpdate = DateTime.MinValue;
private readonly TimeSpan _relevantMessagesCountCacheDuration = TimeSpan.FromMilliseconds(500);
private DateTime _maxRelevantMessagesCountSetTime = DateTime.MinValue;
private readonly TimeSpan _relevantMessagesCountCacheDuration = TimeSpan.FromMilliseconds(100);
private readonly TimeSpan _maxRelevantValueHoldDuration = TimeSpan.FromSeconds(2);
private readonly object _relevantMessagesCountLock = new object();

/// <summary>
Expand All @@ -83,7 +104,9 @@ public int? ActiveMessagesCount
/// <remarks>
/// The RelevantMessagesCount property will return the number of messengers that have a state greater than eAxoMessengerState.Idle.
/// Messengers is a collection of objects that represents messengers.
/// The value is cached for a short period to prevent flickering due to asynchronous PLC communication.
/// The value uses a maximum-tracking mechanism to prevent flickering caused by PLC cycle timing,
/// where the message count is accumulated during each controller cycle starting from 0.
/// The maximum value seen is held for a period since the correct full count persists longer than partial counts.
/// </remarks>
/// <returns>An integer that represents the count of relevant messages.</returns>
public int? RelevantMessagesCount
Expand All @@ -94,11 +117,11 @@ public int? RelevantMessagesCount
{
var now = DateTime.UtcNow;

// Return cached value if still valid
// Return cached value if we just read recently
if (_cachedRelevantMessagesCount.HasValue &&
(now - _lastRelevantMessagesCountUpdate) < _relevantMessagesCountCacheDuration)
{
return _cachedRelevantMessagesCount;
return _maxRelevantMessagesCount ?? _cachedRelevantMessagesCount;
}

try
Expand All @@ -111,7 +134,20 @@ public int? RelevantMessagesCount
_cachedRelevantMessagesCount = count;
_lastRelevantMessagesCountUpdate = now;

return count;
// Track maximum value seen
if (!_maxRelevantMessagesCount.HasValue || count > _maxRelevantMessagesCount.Value)
{
_maxRelevantMessagesCount = count;
_maxRelevantMessagesCountSetTime = now;
}
// Reset max if hold duration has passed and current value is lower
else if ((now - _maxRelevantMessagesCountSetTime) > _maxRelevantValueHoldDuration)
{
_maxRelevantMessagesCount = count;
_maxRelevantMessagesCountSetTime = now;
}

return _maxRelevantMessagesCount;
}
catch (Exception e)
{
Expand Down Expand Up @@ -243,13 +279,17 @@ public void InvalidateMessageCountCache()
lock (_activeMessagesCountLock)
{
_cachedActiveMessagesCount = null;
_maxActiveMessagesCount = null;
_lastActiveMessagesCountUpdate = DateTime.MinValue;
_maxActiveMessagesCountSetTime = DateTime.MinValue;
}

lock (_relevantMessagesCountLock)
{
_cachedRelevantMessagesCount = null;
_maxRelevantMessagesCount = null;
_lastRelevantMessagesCountUpdate = DateTime.MinValue;
_maxRelevantMessagesCountSetTime = DateTime.MinValue;
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions src/inspectors/ctrl/src/AxoInspectorDialog.st
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@ NAMESPACE AXOpen.Inspectors
_inspectorIndentity : ULINT; //try display inspector inside dialog.
_inspectionDetails : STRING[254];
_inspectorType : eInspectorType;
{#ix-set:AttributeName = "<#Data#>"}
{#ix-set:AttributeName = ""}
{#ix-set:Units = ""}
_analogInspectorData : AxoAnalogueInspectorData;
{#ix-set:AttributeName = "<#Data#>"}
{#ix-set:AttributeName = ""}
{#ix-set:Units = ""}
_digitalInspectorData : AxoDigitalInspectorData;
{#ix-set:AttributeName = "<#Data#>"}
{#ix-set:AttributeName = ""}
{#ix-set:Units = ""}
_dataInspectorData : AxoDataInspectorData;
END_VAR

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,23 @@
[Parameter]
public string Presentation { get; set; }


private string _name;
[Parameter]
public string Name { get; set; }
public string Name
{
get
{
return this._name == this.Data.GetSymbolTail() ? string.Empty : this._name;
}

set
{
this._name = value;
}
}

private string NameWithUnit => string.IsNullOrEmpty(this.Data?.Units) ? this.Name : $"{Name} [{this.Data.Units}]";
private string NameWithUnit => string.IsNullOrEmpty(this.Data?.Units) || this.Data?.Units == this.Data?.GetSymbolTail() ? this.Name : $"{Name} [{this.Data.Units}]";


private short Result
Expand Down
Loading