OSDP.Net 5.2.1
A .NET library for implementing the Open Supervised Device Protocol (OSDP)
Loading...
Searching...
No Matches
LineQualityReport.cs
1using System;
2using System.Collections.Generic;
3using System.Linq;
4
6{
11 {
14
17
20
23 }
24
28 public class CombinationResult
29 {
30 private readonly List<double> _responseTimesMs = new List<double>();
31
32 internal CombinationResult(TestPattern pattern, int payloadLength)
33 {
34 Pattern = pattern;
35 PayloadLength = payloadLength;
36 }
37
39 public TestPattern Pattern { get; }
40
42 public int PayloadLength { get; }
43
45 public int PacketsSent { get; internal set; }
46
48 public int PacketsReceived { get; internal set; }
49
51 public int Timeouts { get; internal set; }
52
54 public int IntegrityErrors { get; internal set; }
55
57 public int Naks { get; internal set; }
58
63 public int PatternMismatches { get; internal set; }
64
67
69 public double SuccessRatePercent =>
70 PacketsSent == 0 ? 0.0 : 100.0 * PacketsReceived / PacketsSent;
71
73 public double MinResponseTimeMs => _responseTimesMs.Count == 0 ? 0.0 : _responseTimesMs.Min();
74
76 public double MaxResponseTimeMs => _responseTimesMs.Count == 0 ? 0.0 : _responseTimesMs.Max();
77
79 public double AverageResponseTimeMs => _responseTimesMs.Count == 0 ? 0.0 : _responseTimesMs.Average();
80
81 internal void RecordResponseTime(double milliseconds) => _responseTimesMs.Add(milliseconds);
82 }
83
87 public class BaudRateResult
88 {
89 private readonly List<CombinationResult> _combinations = new List<CombinationResult>();
90
91 internal BaudRateResult(int baudRate)
92 {
93 BaudRate = baudRate;
94 }
95
97 public int BaudRate { get; }
98
100 public IReadOnlyList<CombinationResult> Combinations => _combinations;
101
109 public string SkipReason { get; internal set; }
110
119 public string FailureReason { get; internal set; }
120
122 public bool WasTested => SkipReason == null && FailureReason == null && PacketsSent > 0;
123
125 public int PacketsSent => _combinations.Sum(combination => combination.PacketsSent);
126
128 public int PacketsReceived => _combinations.Sum(combination => combination.PacketsReceived);
129
131 public int Timeouts => _combinations.Sum(combination => combination.Timeouts);
132
134 public int IntegrityErrors => _combinations.Sum(combination => combination.IntegrityErrors);
135
137 public int Naks => _combinations.Sum(combination => combination.Naks);
138
140 public int PatternMismatches => _combinations.Sum(combination => combination.PatternMismatches);
141
144
146 public double SuccessRatePercent =>
147 PacketsSent == 0 ? 0.0 : 100.0 * PacketsReceived / PacketsSent;
148
150 public double MaxResponseTimeMs =>
151 _combinations.Count == 0 ? 0.0 : _combinations.Max(combination => combination.MaxResponseTimeMs);
152
155 {
156 get
157 {
158 int received = PacketsReceived;
159 if (received == 0) return 0.0;
160
161 double weighted = _combinations.Sum(combination =>
162 combination.AverageResponseTimeMs * combination.PacketsReceived);
163 return weighted / received;
164 }
165 }
166
173
182 {
183 get
184 {
185 // An incomplete rate change is a failure of the rate, even though it produced no
186 // packets to count. Reporting it as merely "untested" would hide the finding.
187 if (FailureReason != null) return LineQualityVerdict.Fail;
188
189 if (!WasTested) return LineQualityVerdict.Untested;
190
192 {
193 return LineQualityVerdict.Fail;
194 }
195
196 if (Failures > 0 || MaxResponseTimeMs > MarginalReplyDelayMs)
197 {
198 return LineQualityVerdict.Marginal;
199 }
200
201 return LineQualityVerdict.Pass;
202 }
203 }
204
206 internal const double MaximumReplyDelayMs = 200.0;
207
209 internal const double MarginalReplyDelayMs = 150.0;
210
211 internal CombinationResult AddCombination(TestPattern pattern, int payloadLength)
212 {
213 var combination = new CombinationResult(pattern, payloadLength);
214 _combinations.Add(combination);
215 return combination;
216 }
217 }
218
222 public class LineQualityReport
223 {
224 private readonly List<BaudRateResult> _baudRates = new List<BaudRateResult>();
225
226 internal LineQualityReport(TestProfile profile, string connection, byte address)
227 {
228 Profile = profile;
229 Connection = connection;
230 Address = address;
231 StartedUtc = DateTime.UtcNow;
232 }
233
235 public TestProfile Profile { get; }
236
238 public string Connection { get; }
239
241 public byte Address { get; }
242
244 public DateTime StartedUtc { get; }
245
247 public DateTime CompletedUtc { get; internal set; }
248
250 public TimeSpan Duration => CompletedUtc - StartedUtc;
251
253 public IReadOnlyList<BaudRateResult> BaudRates => _baudRates;
254
259
267 public int? RecommendedBaudRate => _baudRates
268 .Where(result => result.Verdict == LineQualityVerdict.Pass)
269 .Select(result => (int?)result.BaudRate)
270 .DefaultIfEmpty(null)
271 .Max();
272
277 {
278 get
279 {
280 // A rate that failed its transition counts here even though it produced no packets.
281 var assessed = _baudRates
282 .Where(result => result.Verdict != LineQualityVerdict.Untested)
283 .ToArray();
284
285 if (assessed.Length == 0) return LineQualityVerdict.Untested;
286
287 if (assessed.Any(result => result.Verdict == LineQualityVerdict.Pass))
288 {
289 return LineQualityVerdict.Pass;
290 }
291
292 return assessed.Any(result => result.Verdict == LineQualityVerdict.Marginal)
294 : LineQualityVerdict.Fail;
295 }
296 }
297
298 internal BaudRateResult AddBaudRate(int baudRate)
299 {
300 var result = new BaudRateResult(baudRate);
301 _baudRates.Add(result);
302 return result;
303 }
304 }
305}
Results for every combination exercised at a single baud rate.
int Failures
Gets the total number of failures of any kind at this rate.
double AverageResponseTimeMs
Gets the mean response time across every successful exchange at this rate.
LineQualityVerdict Verdict
Gets the assessment for this baud rate, per section 6.1 of the test procedure.
IReadOnlyList< CombinationResult > Combinations
Gets the per-combination results.
string FailureReason
Gets the reason the rate failed before any packets could be measured, or null.
bool WasTested
Gets a value indicating whether any packets were sent at this rate.
int PatternMismatches
Gets the total number of pattern mismatches at this rate.
double MaxResponseTimeMs
Gets the longest response time observed at this rate, in milliseconds.
int Naks
Gets the total number of NAK replies at this rate.
int PacketsSent
Gets the total number of echo requests sent at this rate.
int PacketsReceived
Gets the total number of correct echoes received at this rate.
int IntegrityErrors
Gets the total number of integrity failures at this rate.
double DetectionLimitPercent
Gets the smallest packet loss rate this run could have ruled out, as a percentage.
int Timeouts
Gets the total number of timeouts at this rate.
int BaudRate
Gets the baud rate these results describe.
string SkipReason
Gets the reason the rate was not exercised because the responder cannot do it, or null.
double SuccessRatePercent
Gets the proportion of requests that produced a correct echo, as a percentage.
Results for a single pattern and payload size at one baud rate.
int Failures
Gets the total number of failures of any kind.
double SuccessRatePercent
Gets the proportion of requests that produced a correct echo, as a percentage.
int PacketsReceived
Gets the number of correct echoes received.
double AverageResponseTimeMs
Gets the mean observed response time, or zero when nothing was received.
int Timeouts
Gets the number of requests that drew no reply within the timeout.
int PacketsSent
Gets the number of echo requests sent.
int PayloadLength
Gets the payload length exercised.
TestPattern Pattern
Gets the pattern exercised.
double MaxResponseTimeMs
Gets the longest observed response time, or zero when nothing was received.
int IntegrityErrors
Gets the number of replies that arrived but failed their integrity check.
int Naks
Gets the number of replies that were a NAK.
double MinResponseTimeMs
Gets the shortest observed response time, or zero when nothing was received.
int PatternMismatches
Gets the number of replies that passed their integrity check but did not carry the expected sequence ...
Constants and helpers for the OSDP Line Quality Test Procedure.
static double DetectionLimitPercent(int packetsSent)
Calculates the smallest packet loss rate a run of the given size can rule out, as a percentage,...
static int IterationsPerCombination(TestProfile profile)
Returns the number of iterations a profile runs for each pattern and size combination.
DateTime CompletedUtc
Gets when the run finished.
int? RecommendedBaudRate
Gets the highest baud rate that passed, or null when none did.
string Connection
Gets a description of the connection tested.
byte Address
Gets the responder address that was tested.
TestProfile Profile
Gets the profile the run used.
IReadOnlyList< BaudRateResult > BaudRates
Gets the per-baud-rate results, in the order they were exercised.
LineQualityVerdict OverallVerdict
Gets the overall verdict: the best result achieved at any rate.
TimeSpan Duration
Gets how long the run took.
DateTime StartedUtc
Gets when the run started.
int IterationsPerCombination
Gets the number of iterations run for each pattern and payload combination.
TestPattern
Test pattern identifiers defined by the OSDP Line Quality Test Procedure, section 3....
TestProfile
Test profiles from section 3.10 of the Line Quality Test Procedure.
LineQualityVerdict
The overall assessment of a baud rate or of a whole test run.
@ Marginal
Usable, but with at least one failure or a response time approaching the limit.
@ Pass
No failures of any kind, and every response comfortably inside the reply window.
@ Untested
The rate was not exercised, usually because the responder refused to switch to it.