< Summary - pva.SuperV

Information
Class: pva.SuperV.Engine.Processing.AlarmStateProcessing<T>
Assembly: pva.SuperV.Engine
File(s): /home/runner/work/pva.SuperV/pva.SuperV/pva.SuperV.Engine/Processing/AlarmStateProcessing.cs
Tag: dotnet-ubuntu_22190969454
Line coverage
97%
Covered lines: 91
Uncovered lines: 2
Coverable lines: 93
Total lines: 240
Line coverage: 97.8%
Branch coverage
81%
Covered branches: 44
Total branches: 54
Branch coverage: 81.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_HighHighLimitField()100%11100%
get_HighLimitField()100%11100%
get_LowLimitField()100%11100%
get_LowLowLimitField()100%11100%
get_DeadbandField()100%11100%
get_AlarmStateField()100%11100%
get_AckStateField()100%11100%
.ctor()100%11100%
.ctor(...)75%88100%
BuildAfterDeserialization(...)100%11100%
ValidateParameters(...)100%11100%
IsFieldUsed(...)100%1212100%
IsFieldUsed(...)50%22100%
ProcessValue(...)78.12%323294.87%

File(s)

/home/runner/work/pva.SuperV/pva.SuperV/pva.SuperV.Engine/Processing/AlarmStateProcessing.cs

#LineLine coverage
 1using System.Numerics;
 2
 3namespace pva.SuperV.Engine.Processing
 4{
 5    /// <summary>
 6    /// Alarm state generation processing on a field.
 7    /// It sets the alarm state based on a 2 or 4 limits with optional deadband and optionally sets an acknowledgement.
 8    /// </summary>
 9    /// <typeparam name="T">Type of field on which alarm state processing is applied.</typeparam>
 10    /// <seealso cref="FieldValueProcessing{T}" />
 11    public class AlarmStateProcessing<T> : FieldValueProcessing<T>, IAlarmStateProcessing where T : INumber<T>
 12    {
 13        /// <summary>
 14        /// The high-high alarm state value.
 15        /// </summary>
 16        private const int HighHighAlarmState = 2;
 17
 18        /// <summary>
 19        /// The high alarm state value.
 20        /// </summary>
 21        private const int HighAlarmState = 1;
 22
 23        /// <summary>
 24        /// The ok alarm state value
 25        /// </summary>
 26        private const int OkAlarmState = 0;
 27
 28        /// <summary>
 29        /// The low alarm state value.
 30        /// </summary>
 31        private const int LowAlarmState = -1;
 32
 33        /// <summary>
 34        /// The low-low alarm state value.
 35        /// </summary>
 36        private const int LowLowAlarmState = -2;
 37
 38        /// <summary>
 39        /// The unacknowledge state value.
 40        /// </summary>
 41        private const int UnackState = 1;
 42
 43        /// <summary>
 44        /// Gets or sets the high-high limit field definition.
 45        /// </summary>
 46        /// <value>
 47        /// The high-high limit field definition.
 48        /// </value>
 22649        public IFieldDefinition? HighHighLimitField { get; set; }
 50
 51        /// <summary>
 52        /// Gets or sets the high limit field definition.
 53        /// </summary>
 54        /// <value>
 55        /// The high limit field definition.
 56        /// </value>
 22557        public IFieldDefinition? HighLimitField { get; set; }
 58
 59        /// <summary>
 60        /// Gets or sets the low limit field definition.
 61        /// </summary>
 62        /// <value>
 63        /// The low limit field definition.
 64        /// </value>
 22465        public IFieldDefinition? LowLimitField { get; set; }
 66
 67        /// <summary>
 68        /// Gets or sets the low-low limit field definition.
 69        /// </summary>
 70        /// <value>
 71        /// The low-low limit field definition.
 72        /// </value>
 22373        public IFieldDefinition? LowLowLimitField { get; set; }
 74
 75        /// <summary>
 76        /// Gets or sets the deadband field definition.
 77        /// </summary>
 78        /// <value>
 79        /// The deadband field definition.
 80        /// </value>
 19981        public IFieldDefinition? DeadbandField { get; set; }
 82
 83        /// <summary>
 84        /// Gets or sets the alarm state field definition.
 85        /// </summary>
 86        /// <value>
 87        /// The alarm state field definition.
 88        /// </value>
 22189        public IFieldDefinition? AlarmStateField { get; set; }
 90
 91        /// <summary>
 92        /// Gets or sets the acknowledgement state field definition.
 93        /// </summary>
 94        /// <value>
 95        /// The acknowledgement state field definition.
 96        /// </value>
 22097        public IFieldDefinition? AckStateField { get; set; }
 98
 99        /// <summary>
 100        /// Initializes a new instance of the <see cref="AlarmStateProcessing{T}"/> class. Used for deserialization.
 101        /// </summary>
 1102        public AlarmStateProcessing()
 1103        {
 1104        }
 105
 106        /// <summary>
 107        /// Initializes a new instance of the <see cref="AlarmStateProcessing{T}"/> class.
 108        /// </summary>
 109        /// <param name="name">The name of processing.</param>
 110        /// <param name="clazz">The class of the instance to be processed.</param>
 111        /// <param name="trigerringFieldName">Name of the trigerring field.</param>
 112        /// <param name="highHighLimitFieldName">Name of the high-high limit field. Can be null/empty if not used.</para
 113        /// <param name="highLimitFieldName">Name of the high limit field.</param>
 114        /// <param name="lowLimitFieldName">Name of the low limit field.</param>
 115        /// <param name="lowLowLimitFieldName">Name of the low-low limit field. Can be null/empty if not used.</param>
 116        /// <param name="deadbandFieldName">Name of the deadband field. Can be null/empty if not used.</param>
 117        /// <param name="alarmStateFieldName">Name of the alarm state field.</param>
 118        /// <param name="ackStateFieldName">Name of the acknowledgment state field. Can be null/empty if not used</param
 119        public AlarmStateProcessing(string name, Class clazz, string trigerringFieldName,
 120            string? highHighLimitFieldName, string highLimitFieldName, string lowLimitFieldName, string? lowLowLimitFiel
 121            string? deadbandFieldName, string alarmStateFieldName, string? ackStateFieldName)
 178122            : base(name)
 178123        {
 178124            CtorArguments.Add(trigerringFieldName);
 178125            CtorArguments.Add(highHighLimitFieldName ?? "");
 178126            CtorArguments.Add(highLimitFieldName);
 178127            CtorArguments.Add(lowLimitFieldName);
 178128            CtorArguments.Add(lowLowLimitFieldName ?? "");
 178129            CtorArguments.Add(deadbandFieldName ?? "");
 178130            CtorArguments.Add(alarmStateFieldName);
 178131            CtorArguments.Add(ackStateFieldName ?? "");
 132
 178133            ValidateParameters(clazz, trigerringFieldName,
 178134                highHighLimitFieldName, highLimitFieldName, lowLimitFieldName, lowLowLimitFieldName, deadbandFieldName,
 178135                alarmStateFieldName, ackStateFieldName);
 178136        }
 137
 138        /// <summary>
 139        /// Builds the field value processing from the <see cref="P:pva.SuperV.Engine.FieldValueProcessing`1.CtorArgumen
 140        /// </summary>
 141        /// <param name="project">The project.</param>
 142        /// <param name="clazz">The clazz.</param>
 143        public override void BuildAfterDeserialization(Project project, Class clazz)
 1144        {
 1145            string? trigerringFieldName = GetCtorArgument<string>(0);
 1146            string? highHighLimitFieldName = GetCtorArgument<string>(1);
 1147            string? highLimitFieldName = GetCtorArgument<string>(2);
 1148            string? lowLimitFieldName = GetCtorArgument<string>(3);
 1149            string? lowLowLimitFieldName = GetCtorArgument<string>(4);
 1150            string? deadbandFieldName = GetCtorArgument<string>(5);
 1151            string? alarmStateFieldName = GetCtorArgument<string>(6);
 1152            string? ackStateFieldName = GetCtorArgument<string>(7);
 153
 1154            ValidateParameters(clazz, trigerringFieldName,
 1155                highHighLimitFieldName, highLimitFieldName, lowLimitFieldName, lowLowLimitFieldName, deadbandFieldName,
 1156                alarmStateFieldName, ackStateFieldName);
 1157        }
 158
 159        private void ValidateParameters(Class clazz, string? trigerringFieldName, string? highHighLimitFieldName, string
 179160        {
 179161            TrigerringFieldDefinition = GetFieldDefinition<T>(clazz, trigerringFieldName);
 179162            HighHighLimitField = GetFieldDefinition<T>(clazz, highHighLimitFieldName);
 179163            HighLimitField = GetFieldDefinition<T>(clazz, highLimitFieldName)!;
 179164            LowLimitField = GetFieldDefinition<T>(clazz, lowLimitFieldName)!;
 179165            LowLowLimitField = GetFieldDefinition<T>(clazz, lowLowLimitFieldName);
 179166            DeadbandField = GetFieldDefinition<T>(clazz, deadbandFieldName);
 179167            AlarmStateField = GetFieldDefinition<int>(clazz, alarmStateFieldName)!;
 179168            AckStateField = GetFieldDefinition<int>(clazz, ackStateFieldName)!;
 179169        }
 170
 171        public override bool IsFieldUsed(string fieldName)
 7172        => IsFieldUsed(HighHighLimitField, fieldName) || IsFieldUsed(HighLimitField, fieldName) ||
 7173            IsFieldUsed(LowLimitField, fieldName) || IsFieldUsed(LowLowLimitField, fieldName) ||
 7174            IsFieldUsed(DeadbandField, fieldName) ||
 7175            IsFieldUsed(AlarmStateField, fieldName) || IsFieldUsed(AckStateField, fieldName);
 176
 177        private static bool IsFieldUsed(IFieldDefinition? field, string fieldName)
 28178        {
 28179            return field?.Name.Equals(fieldName) == true;
 28180        }
 181
 182        /// <summary>
 183        /// Processes the value change.
 184        /// </summary>
 185        /// <param name="instance">Instance on which the triggering field changed.</param>
 186        /// <param name="changedField">The <see cref="Field{T}" /> which changed.</param>
 187        /// <param name="valueChanged">If <c>true</c>, indicates that the trigerring field value changed.</param>
 188        /// <param name="previousValue">The previous value of field.</param>
 189        /// <param name="currentValue">The current value of field.</param>
 190        public override void ProcessValue(IInstance instance, Field<T> changedField, bool valueChanged, T previousValue,
 23191        {
 23192            if (!valueChanged)
 0193            {
 0194                return;
 195            }
 23196            Field<T>? highHighLimit = GetInstanceField<T>(instance, HighHighLimitField?.Name);
 23197            Field<T>? highLimit = GetInstanceField<T>(instance, HighLimitField!.Name);
 23198            Field<T>? lowLimit = GetInstanceField<T>(instance, LowLimitField!.Name);
 23199            Field<T>? lowLowLimit = GetInstanceField<T>(instance, LowLowLimitField?.Name);
 200            // TODO: Add deadband
 201            // Field<T>? deadband = GetInstanceField<T>(instance, DeadbandField?.Name);
 23202            Field<int> alarmState = GetInstanceField<int>(instance, AlarmStateField!.Name)!;
 23203            Field<int>? ackState = GetInstanceField<int>(instance, AckStateField?.Name);
 23204            int previousAlarmState = alarmState.Value;
 205            int newAlarmState;
 206            // TODO: Handle deadband
 23207            if (highHighLimit is not null && currentValue >= highHighLimit.Value)
 10208            {
 10209                newAlarmState = HighHighAlarmState;
 10210            }
 13211            else if (highHighLimit is not null && currentValue < highHighLimit.Value && currentValue >= highLimit!.Value
 2212            {
 2213                newAlarmState = HighAlarmState;
 2214            }
 11215            else if (lowLowLimit is not null && currentValue <= lowLowLimit.Value)
 2216            {
 2217                newAlarmState = LowLowAlarmState;
 2218            }
 9219            else if (currentValue <= lowLimit!.Value)
 3220            {
 3221                newAlarmState = LowAlarmState;
 3222            }
 223            else
 6224            {
 6225                newAlarmState = OkAlarmState;
 6226            }
 227
 23228            if (newAlarmState == previousAlarmState)
 2229            {
 2230                return;
 231            }
 232
 21233            alarmState.SetValue(newAlarmState);
 21234            if (ackState is not null && newAlarmState != OkAlarmState && ackState.Value != UnackState)
 9235            {
 9236                ackState.SetValue(UnackState);
 9237            }
 23238        }
 239    }
 240}