PROFINET IO Controller Stack 1.0.0
Modern C++ implementation of a PROFINET IO Controller stack
Loading...
Searching...
No Matches
test_diagnosisMore.cpp
Go to the documentation of this file.
1
8
9#include <gtest/gtest.h>
10
11#include <cstdint>
12#include <vector>
13
14#include "profinet/diagnosis.h"
15#include "profinet/wire.h"
16
17using namespace profinet;
18using namespace profinet::diagnosis;
19
20namespace
21{
26Bytes MakeDiagnosisHeader(const std::uint16_t bodyLength, const std::uint16_t type = 0x0010)
27{
28 Bytes data;
29 wire::PutU16(data, type);
30 wire::PutU16(data, static_cast<std::uint16_t>(bodyLength + 2U));
31 wire::PutU8(data, 1);
32 wire::PutU8(data, 0);
33 return data;
34}
35
42Bytes MakeEntry(const std::uint16_t channel, const std::uint16_t properties,
43 const std::uint16_t usi, const std::uint16_t errorType)
44{
45 Bytes out;
46 wire::PutU16(out, channel);
47 wire::PutU16(out, properties);
48 wire::PutU16(out, usi);
49 wire::PutU16(out, errorType);
50 return out;
51}
52
60Bytes MakeExtendedEntry(const std::uint16_t channel, const std::uint16_t properties,
61 const std::uint16_t errorType, const std::uint16_t extErrorType,
62 const std::uint32_t extAddValue)
63{
64 Bytes out = MakeEntry(channel, properties,
65 static_cast<std::uint16_t>(Usi::Bit15AndExternalChannelDiagnosisOfChannelNumber), errorType);
66 wire::PutU16(out, extErrorType);
67 wire::PutU32(out, extAddValue);
68 return out;
69}
70
79Bytes MakeQualifiedEntry(const std::uint16_t channel, const std::uint16_t properties,
80 const std::uint16_t errorType, const std::uint16_t extErrorType,
81 const std::uint32_t extAddValue, const std::uint32_t qualifier)
82{
83 Bytes out = MakeEntry(channel, properties,
84 static_cast<std::uint16_t>(Usi::Bit15AndQualifiedChannelDiagnosisOfChannelNumber), errorType);
85 wire::PutU16(out, extErrorType);
86 wire::PutU32(out, extAddValue);
87 wire::PutU32(out, qualifier);
88 return out;
89}
90
94Bytes MakeSimpleBlock(const Bytes& entries)
95{
96 Bytes out = MakeDiagnosisHeader(static_cast<std::uint16_t>(entries.size()));
97 out.insert(out.end(), entries.begin(), entries.end());
98 return out;
99}
100
101} // namespace
102
103namespace
104{
106class DiagnosisMoreTests : public ::testing::Test
107{
108};
109} // namespace
110
112TEST_F(DiagnosisMoreTests, ChannelTypeNamesCoverAllValues)
113{
114 ChannelProperties props;
115
116 props.channelTypeValue = ChannelType::Reserved;
117 EXPECT_EQ(props.ChannelTypeName(), "Reserved");
118
119 props.channelTypeValue = ChannelType::Specific;
120 EXPECT_EQ(props.ChannelTypeName(), "Specific");
121
122 props.channelTypeValue = ChannelType::All;
123 EXPECT_EQ(props.ChannelTypeName(), "All");
124
125 props.channelTypeValue = ChannelType::Submodule;
126 EXPECT_EQ(props.ChannelTypeName(), "Submodule");
127
128 props.channelTypeValue = static_cast<ChannelType>(0xFF);
129 EXPECT_FALSE(props.ChannelTypeName().empty());
130}
131
133TEST_F(DiagnosisMoreTests, SpecifierNamesCoverAllValues)
134{
135 ChannelProperties props;
136
137 props.specifier = ChannelSpecifier::AllDisappears;
138 EXPECT_EQ(props.SpecifierName(), "All Disappears");
139
140 props.specifier = ChannelSpecifier::Appears;
141 EXPECT_EQ(props.SpecifierName(), "Appears");
142
143 props.specifier = ChannelSpecifier::Disappears;
144 EXPECT_EQ(props.SpecifierName(), "Disappears");
145
146 props.specifier = ChannelSpecifier::DisappearsOther;
147 EXPECT_EQ(props.SpecifierName(), "Disappears Other");
148
149 props.specifier = static_cast<ChannelSpecifier>(0xFF);
150 EXPECT_FALSE(props.SpecifierName().empty());
151}
152
154TEST_F(DiagnosisMoreTests, DirectionNamesCoverAllValues)
155{
156 ChannelProperties props;
157
158 props.direction = ChannelDirection::Manufacturer;
159 EXPECT_EQ(props.DirectionName(), "Manufacturer");
160
161 props.direction = ChannelDirection::Input;
162 EXPECT_EQ(props.DirectionName(), "Input");
163
164 props.direction = ChannelDirection::Output;
165 EXPECT_EQ(props.DirectionName(), "Output");
166
167 props.direction = ChannelDirection::Bidirectional;
168 EXPECT_EQ(props.DirectionName(), "Bidirectional");
169
170 props.direction = static_cast<ChannelDirection>(0xFF);
171 EXPECT_FALSE(props.DirectionName().empty());
172}
173
175TEST_F(DiagnosisMoreTests, ChannelPropertiesFromUint16RetainsRawValue)
176{
177 const auto props = ChannelProperties::FromUint16(0xFFFF);
178
179 EXPECT_EQ(props.raw, 0xFFFFU);
180 EXPECT_EQ(props.channelTypeValue, ChannelType::Submodule);
181 EXPECT_EQ(props.accumulative, ChannelAccumulative::No);
182 EXPECT_EQ(props.specifier, ChannelSpecifier::AllDisappears);
183 EXPECT_EQ(props.direction, ChannelDirection::Bidirectional);
184}
185
187TEST_F(DiagnosisMoreTests, AnyChannelDiagnosisUsiClassification)
188{
190 entry.usi = Usi::NoIdentifier;
191 EXPECT_TRUE(entry.IsChannelDiagnosis());
192 EXPECT_FALSE(entry.IsExtChannelDiagnosis());
193 EXPECT_FALSE(entry.IsQualifiedChannelDiagnosis());
194
195 entry.usi = Usi::Bit15OfChannelNumber;
196 EXPECT_TRUE(entry.IsChannelDiagnosis());
197
198 entry.usi = Usi::Bit15AndExternalChannelDiagnosisOfChannelNumber;
199 EXPECT_TRUE(entry.IsExtChannelDiagnosis());
200 EXPECT_FALSE(entry.IsQualifiedChannelDiagnosis());
201
202 entry.usi = Usi::Bit15AndQualifiedChannelDiagnosisOfChannelNumber;
203 EXPECT_TRUE(entry.IsQualifiedChannelDiagnosis());
204 EXPECT_FALSE(entry.IsExtChannelDiagnosis());
205}
206
208TEST_F(DiagnosisMoreTests, DiagnosisDataMaintenanceFlagsAreFalseWhenClear)
209{
210 DiagnosisData data;
211
213 entry.base.properties.maintenanceRequired = false;
214 entry.base.properties.naintenanceDemanded = false;
215 data.entries.push_back(entry);
216
217 EXPECT_FALSE(data.HasMaintenanceRequired());
218 EXPECT_FALSE(data.HasMaintenanceDemanded());
219}
220
222TEST_F(DiagnosisMoreTests, DiagnosisDataDetectsMaintenanceDemanded)
223{
224 DiagnosisData data;
225
228 data.entries.push_back(entry);
229
230 EXPECT_TRUE(data.HasMaintenanceDemanded());
231 EXPECT_FALSE(data.HasMaintenanceRequired());
232}
233
235TEST_F(DiagnosisMoreTests, DecodeChannelErrorTypeCoversAdditionalRanges)
236{
237 EXPECT_EQ(DecodeChannelErrorType(0x8001), "Remote mismatch");
238 EXPECT_FALSE(DecodeChannelErrorType(0x8100).empty());
239 EXPECT_EQ(DecodeChannelErrorType(0x0100), "Manufacturer-specific (0x0100)");
240}
241
243TEST_F(DiagnosisMoreTests, DecodeExtChannelErrorTypeHandlesUnknownValues)
244{
245 EXPECT_EQ(DecodeExtChannelErrorType(0x8001, 0x8005), "No peer detected");
246
247 EXPECT_EQ(DecodeExtChannelErrorType(0x8001, 0x1234), "Manufacturer-specific (0x1234)");
248}
249
251TEST_F(DiagnosisMoreTests, ParseDiagnosisBlockAcceptsUsiZero)
252{
253 Bytes body = MakeEntry(4, 0, 0, 0x0001);
254 Bytes data = MakeDiagnosisHeader(static_cast<std::uint16_t>(body.size()));
255 data.insert(data.end(), body.begin(), body.end());
256
257 const auto result = ParseDiagnosisBlock(data, 7, 8, 9);
258
259 ASSERT_EQ(result.entries.size(), 1U);
260 EXPECT_EQ(result.entries[0].base.api, 7U);
261 EXPECT_EQ(result.entries[0].base.slot, 8U);
262 EXPECT_EQ(result.entries[0].base.subslot, 9U);
263 EXPECT_TRUE(result.entries[0].IsChannelDiagnosis());
264}
265
267TEST_F(DiagnosisMoreTests, ParseDiagnosisBlockStoresExtendedDiagnosis)
268{
269 Bytes body = MakeExtendedEntry(2, 0, 0x8001, 0x8005, 0x11223344);
270 Bytes data = MakeDiagnosisHeader(static_cast<std::uint16_t>(body.size()));
271 data.insert(data.end(), body.begin(), body.end());
272
273 const auto result = ParseDiagnosisBlock(data);
274
275 ASSERT_EQ(result.entries.size(), 1U);
276 ASSERT_TRUE(result.entries[0].ext.has_value());
277 EXPECT_EQ(result.entries[0].ext->extErrorType, 0x8005U);
278 EXPECT_EQ(result.entries[0].ext->extAddValue, 0x11223344U);
279 EXPECT_EQ(result.entries[0].ext->extErrorTypeName, "No peer detected");
280}
281
283TEST_F(DiagnosisMoreTests, ParseDiagnosisBlockStoresQualifiedDiagnosis)
284{
285 Bytes body = MakeQualifiedEntry(3, 0, 0x8000, 0x8000, 0x01020304, 0xAABBCCDD);
286 Bytes data = MakeDiagnosisHeader(static_cast<std::uint16_t>(body.size()));
287 data.insert(data.end(), body.begin(), body.end());
288
289 const auto result = ParseDiagnosisBlock(data);
290
291 ASSERT_EQ(result.entries.size(), 1U);
292 ASSERT_TRUE(result.entries[0].qualified.has_value());
293 EXPECT_EQ(result.entries[0].qualified->extErrorType, 0x8000U);
294 EXPECT_EQ(result.entries[0].qualified->extAddValue, 0x01020304U);
295 EXPECT_EQ(result.entries[0].qualified->qualifier, 0xAABBCCDDU);
296}
297
299TEST_F(DiagnosisMoreTests, ParseDiagnosisBlockStopsOnTruncatedEntry)
300{
301 Bytes data = MakeDiagnosisHeader(5);
302 data.insert(data.end(), {0, 1, 0, 0, 0});
303
304 const auto result = ParseDiagnosisBlock(data);
305
306 EXPECT_TRUE(result.entries.empty());
307}
308
310TEST_F(DiagnosisMoreTests, ParseDiagnosisBlockStopsOnZeroEntry)
311{
312 Bytes data = MakeDiagnosisHeader(8);
313 data.insert(data.end(), 8, 0);
314
315 const auto result = ParseDiagnosisBlock(data);
316
317 EXPECT_TRUE(result.entries.empty());
318}
319
321TEST_F(DiagnosisMoreTests, ParseDiagnosisBlockAcceptsAlternativeBlockTypes)
322{
323 const std::vector<std::uint16_t> types{0x0010, 0x0011, 0x8010, 0x8011, 0x8012};
324
325 for (const auto type : types)
326 {
327 Bytes entry = MakeEntry(1, 0, 0x8000, 1);
328 Bytes data = MakeDiagnosisHeader(static_cast<std::uint16_t>(entry.size()), type);
329 data.insert(data.end(), entry.begin(), entry.end());
330
331 const auto result = ParseDiagnosisBlock(data);
332 ASSERT_EQ(result.entries.size(), 1U) << "type=0x" << std::hex << type;
333 }
334}
335
337TEST_F(DiagnosisMoreTests, ParseDiagnosisBlockAcceptsRawEntry)
338{
339 const Bytes data = MakeEntry(1, 0, 0x8000, 1);
340
341 const auto result = ParseDiagnosisBlock(data, 1, 2, 3);
342
343 ASSERT_EQ(result.entries.size(), 1U);
344 EXPECT_EQ(result.entries[0].base.slot, 2U);
345 EXPECT_EQ(result.entries[0].base.subslot, 3U);
346}
347
349TEST_F(DiagnosisMoreTests, ParseDiagnosisSimpleStopsOnIncompleteEntry)
350{
351 Bytes data = MakeDiagnosisHeader(9);
352 wire::PutU16(data, 1);
353 wire::PutU16(data, 0);
354 wire::PutU16(data, 1);
355 wire::PutU16(data, 2);
356 wire::PutU16(data, 0);
357
358 const auto result = ParseDiagnosisSimple(data, 0, 1, 2);
359
360 ASSERT_EQ(result.entries.size(), 1U);
361 EXPECT_EQ(result.entries[0].base.channelNumber, 1U);
362}
363
365TEST_F(DiagnosisMoreTests, ParseDiagnosisSimplePreservesLocation)
366{
367 Bytes data = MakeDiagnosisHeader(12);
368 wire::PutU16(data, 3);
369 wire::PutU16(data, 0);
370 wire::PutU16(data, 1);
371 wire::PutU16(data, 0);
372 wire::PutU16(data, 0);
373 wire::PutU16(data, 0);
374
375 const auto result = ParseDiagnosisSimple(data, 0, 4, 5);
376
377 ASSERT_EQ(result.entries.size(), 1U);
378 EXPECT_EQ(result.entries[0].base.slot, 4U);
379 EXPECT_EQ(result.entries[0].base.subslot, 5U);
380}
382TEST_F(DiagnosisMoreTests, ChannelPropertiesFromUint16CoversAllValidFields)
383{
384 for (std::uint16_t channelType = 0; channelType <= 3; ++channelType)
385 {
386 const auto props = ChannelProperties::FromUint16(channelType);
387 EXPECT_EQ(static_cast<std::uint8_t>(props.channelTypeValue), channelType);
388 }
389
390 for (std::uint16_t accumulative = 0; accumulative <= 2; ++accumulative)
391 {
392 const auto props =
393 ChannelProperties::FromUint16(static_cast<std::uint16_t>(accumulative << 2));
394 EXPECT_EQ(static_cast<std::uint8_t>(props.accumulative), accumulative);
395 }
396
397 const auto maintenance = ChannelProperties::FromUint16(
398 static_cast<std::uint16_t>((1U << 5U) | (1U << 6U)));
399
400 EXPECT_TRUE(maintenance.maintenanceRequired);
401 EXPECT_TRUE(maintenance.naintenanceDemanded);
402
403 for (std::uint16_t specifier = 0; specifier <= 3; ++specifier)
404 {
405 const auto props =
406 ChannelProperties::FromUint16(static_cast<std::uint16_t>(specifier << 8));
407 EXPECT_EQ(static_cast<std::uint8_t>(props.specifier), specifier);
408 }
409
410 for (std::uint16_t direction = 0; direction <= 3; ++direction)
411 {
412 const auto props =
413 ChannelProperties::FromUint16(static_cast<std::uint16_t>(direction << 11));
414 EXPECT_EQ(static_cast<std::uint8_t>(props.direction), direction);
415 }
416}
417
419TEST_F(DiagnosisMoreTests, ChannelPropertiesFromUint16UsesFallbacks)
420{
421 const auto invalidAccumulative = ChannelProperties::FromUint16(3U << 2U);
422 EXPECT_EQ(invalidAccumulative.accumulative, ChannelAccumulative::No);
423
424 const auto invalidSpecifier = ChannelProperties::FromUint16(4U << 8U);
425 EXPECT_EQ(invalidSpecifier.specifier, ChannelSpecifier::AllDisappears);
426}
427
429TEST_F(DiagnosisMoreTests, ChannelDiagnosisDetectsSubmoduleLevel)
430{
431 ChannelDiagnosis diagnosis;
432
433 diagnosis.channelNumber = static_cast<std::uint16_t>(Usi::Bit15OfChannelNumber);
434 EXPECT_TRUE(diagnosis.IsSubmoduleLevel());
435
436 diagnosis.channelNumber = 1;
437 EXPECT_FALSE(diagnosis.IsSubmoduleLevel());
438}
439
441TEST_F(DiagnosisMoreTests, DiagnosisDataGetByChannelFiltersAllMatchingEntries)
442{
443 DiagnosisData data;
444
446 first.base.channelNumber = 7;
447
448 AnyChannelDiagnosis second;
449 second.base.channelNumber = 3;
450
452 third.base.channelNumber = 7;
453
454 data.entries = {first, second, third};
455
456 const auto matches = data.GetByChannel(7);
457
458 ASSERT_EQ(matches.size(), 2U);
459 EXPECT_EQ(matches[0], &data.entries[0]);
460 EXPECT_EQ(matches[1], &data.entries[2]);
461
462 EXPECT_TRUE(data.GetByChannel(99).empty());
463}
464
466TEST_F(DiagnosisMoreTests, DiagnosisDataHasErrorsReflectsEntries)
467{
468 DiagnosisData data;
469
470 EXPECT_FALSE(data.HasErrors());
471
472 data.entries.emplace_back();
473
474 EXPECT_TRUE(data.HasErrors());
475}
476
478TEST_F(DiagnosisMoreTests, DecodeChannelErrorTypeCoversAllFallbackRanges)
479{
480 EXPECT_EQ(DecodeChannelErrorType(0x000B), "Reserved (0x000B)");
481 EXPECT_EQ(DecodeChannelErrorType(0x000E), "Reserved (0x000E)");
482
483 EXPECT_EQ(DecodeChannelErrorType(0x001C), "Unknown (0x001C)");
484
485 EXPECT_EQ(DecodeChannelErrorType(0x0020), "Reserved (0x0020)");
486 EXPECT_EQ(DecodeChannelErrorType(0x00FF), "Reserved (0x00FF)");
487
488 EXPECT_EQ(DecodeChannelErrorType(0x0100), "Manufacturer-specific (0x0100)");
489 EXPECT_EQ(DecodeChannelErrorType(0x7FFF), "Manufacturer-specific (0x7FFF)");
490
491 EXPECT_EQ(DecodeChannelErrorType(0x800E), "Reserved (0x800E)");
492 EXPECT_EQ(DecodeChannelErrorType(0x8FFF), "Reserved (0x8FFF)");
493
494 EXPECT_EQ(DecodeChannelErrorType(0x9000), "Profile-specific (0x9000)");
495 EXPECT_EQ(DecodeChannelErrorType(0x9FFF), "Profile-specific (0x9FFF)");
496
497 EXPECT_EQ(DecodeChannelErrorType(0xA000), "Reserved (0xA000)");
498 EXPECT_EQ(DecodeChannelErrorType(0xFFFF), "Reserved (0xFFFF)");
499}
500
502TEST_F(DiagnosisMoreTests, DecodeExtChannelErrorTypeCoversFallbackRanges)
503{
504 EXPECT_EQ(DecodeExtChannelErrorType(0x1234, 0x0001),
505 "Manufacturer-specific (0x0001)");
506
507 EXPECT_EQ(DecodeExtChannelErrorType(0x1234, 0x8001),
508 "Reserved (0x8001)");
509
510 EXPECT_EQ(DecodeExtChannelErrorType(0x1234, 0x9000),
511 "Profile-specific (0x9000)");
512
513 EXPECT_EQ(DecodeExtChannelErrorType(0x1234, 0x0000),
514 "Reserved");
515
516 EXPECT_EQ(DecodeExtChannelErrorType(0x1234, 0xFFFF),
517 "Unknown (0xFFFF)");
518}
519
521TEST_F(DiagnosisMoreTests, ParseDiagnosisBlockConsumesLocationHeader)
522{
523 Bytes data;
524
525 wire::PutU32(data, 0x00001234);
526 wire::PutU16(data, 7);
527 wire::PutU16(data, 0x8001);
528
529 const Bytes entry = MakeEntry(5, 0, 0x8000, 0x0001);
530 data.insert(data.end(), entry.begin(), entry.end());
531
532 const auto result = ParseDiagnosisBlock(data, 99, 99, 99);
533
534 ASSERT_EQ(result.entries.size(), 1U);
535 EXPECT_EQ(result.entries[0].base.api, 0x1234U);
536 EXPECT_EQ(result.entries[0].base.slot, 7U);
537 EXPECT_EQ(result.entries[0].base.subslot, 0x8001U);
538}
539
541TEST_F(DiagnosisMoreTests, ParseDiagnosisBlockHandlesUnknownUsi)
542{
543 const Bytes data = MakeEntry(4, 0, 0x1234, 0x0009);
544
545 const auto result = ParseDiagnosisBlock(data);
546
547 ASSERT_EQ(result.entries.size(), 1U);
548 EXPECT_EQ(result.entries[0].usi, 0x1234U);
549 EXPECT_EQ(result.entries[0].base.errorType, 0x0009U);
550 EXPECT_EQ(result.entries[0].base.errorTypeName, "Error");
551}
552
554TEST_F(DiagnosisMoreTests, ParseDiagnosisBlockStopsOnTruncatedExtendedDiagnosis)
555{
556 Bytes data = MakeDiagnosisHeader(10);
557 wire::PutU16(data, 1);
558 wire::PutU16(data, 0);
560 data,
561 static_cast<std::uint16_t>(Usi::Bit15AndExternalChannelDiagnosisOfChannelNumber));
562 wire::PutU16(data, 0x8001);
563 wire::PutU16(data, 0x8000);
564
565 const auto result = ParseDiagnosisBlock(data);
566
567 EXPECT_TRUE(result.entries.empty());
568}
569
571TEST_F(DiagnosisMoreTests, ParseDiagnosisBlockStopsOnTruncatedQualifiedDiagnosis)
572{
573 Bytes data = MakeDiagnosisHeader(14);
574 wire::PutU16(data, 1);
575 wire::PutU16(data, 0);
577 data,
578 static_cast<std::uint16_t>(Usi::Bit15AndQualifiedChannelDiagnosisOfChannelNumber));
579 wire::PutU16(data, 0x8000);
580 wire::PutU16(data, 0x8000);
581 wire::PutU32(data, 0x12345678);
582 wire::PutU16(data, 0xABCD);
583
584 const auto result = ParseDiagnosisBlock(data);
585
586 EXPECT_TRUE(result.entries.empty());
587}
588
590TEST_F(DiagnosisMoreTests, ParseDiagnosisBlockRejectsTooShortInput)
591{
592 EXPECT_TRUE(ParseDiagnosisBlock({}).entries.empty());
593 EXPECT_TRUE(ParseDiagnosisBlock(Bytes(5U, 0)).entries.empty());
594}
595
597TEST_F(DiagnosisMoreTests, ParseDiagnosisSimpleRejectsTooShortInput)
598{
599 EXPECT_TRUE(ParseDiagnosisSimple({}).entries.empty());
600 EXPECT_TRUE(ParseDiagnosisSimple(Bytes(5U, 0)).entries.empty());
601}
PROFINET diagnosis data structures, error decoding, and parsers.
std::string DecodeChannelErrorType(std::uint16_t errorType)
Decode a ChannelErrorType to a human-readable string.
ChannelDirection
Data direction, packed into ChannelProperties bits 11-12.
Definition diagnosis.h:76
DiagnosisData ParseDiagnosisSimple(const Bytes &data, std::uint32_t api=0, std::uint16_t slot=0, std::uint16_t subslot=0)
Parse a simple, fixed-format diagnosis block.
DiagnosisData ParseDiagnosisBlock(const Bytes &data, std::uint32_t api=0, std::uint16_t slot=0, std::uint16_t subslot=0)
Parse a full DiagnosisData block from raw bytes.
ChannelType
Channel type, packed into ChannelProperties bits 0-1.
Definition diagnosis.h:39
ChannelSpecifier
Diagnosis specifier, packed into ChannelProperties bits 8-10.
Definition diagnosis.h:63
std::string DecodeExtChannelErrorType(std::uint16_t channelErrorType, std::uint16_t extErrorType)
Decode an ExtChannelErrorType given its ChannelErrorType context.
void PutU8(std::vector< std::uint8_t > &out, std::uint8_t value)
Append a single byte to a buffer.
Definition wire.h:89
void PutU16(std::vector< std::uint8_t > &out, std::uint16_t value)
Append a 16-bit value to a buffer in big-endian order.
Definition wire.h:97
void PutU32(std::vector< std::uint8_t > &out, std::uint32_t value)
Append a 32-bit value to a buffer in big-endian order.
Definition wire.h:105
TEST_F(AlarmListenerTests, InitializesWithEndpoint)
std::vector< std::uint8_t > Bytes
Generic byte buffer alias used throughout the library for raw wire data.
Definition protocol.h:55
Any diagnosis entry (USI 0x8000, 0x8002, or 0x8003).
Definition diagnosis.h:230
bool IsExtChannelDiagnosis() const
Whether this is the ExtChannelDiagnosis variant.
Definition diagnosis.h:254
bool IsQualifiedChannelDiagnosis() const
Whether this is the QualifiedChannelDiagnosis variant.
Definition diagnosis.h:261
Usi usi
The USI that determined which entry type was parsed.
Definition diagnosis.h:232
bool IsChannelDiagnosis() const
Whether this is the plain ChannelDiagnosis variant.
Definition diagnosis.h:247
ChannelDiagnosis base
Common fields, always populated.
Definition diagnosis.h:237
ChannelDiagnosis entry (USI 0x8000).
Definition diagnosis.h:166
std::uint16_t channelNumber
Channel number, with the accumulative bit packed into bit 15.
Definition diagnosis.h:177
bool IsSubmoduleLevel() const
Whether this diagnosis applies to the whole submodule.
Definition diagnosis.h:190
ChannelProperties properties
Decoded channel properties.
Definition diagnosis.h:180
Parsed ChannelProperties word (16 bits).
Definition diagnosis.h:89
std::string SpecifierName() const
Human-readable name for Specifier.
Definition diagnosis.cpp:62
std::string DirectionName() const
Human-readable name for Direction.
Definition diagnosis.cpp:78
bool maintenanceRequired
Maintenance required flag (bit 5).
Definition diagnosis.h:100
bool naintenanceDemanded
Maintenance demanded flag (bit 6).
Definition diagnosis.h:103
std::string ChannelTypeName() const
Human-readable name for ChannelTypeValue.
Definition diagnosis.cpp:46
ChannelType channelTypeValue
Channel type (bits 0-1).
Definition diagnosis.h:94
ChannelDirection direction
Data direction (bits 11-12).
Definition diagnosis.h:109
ChannelSpecifier specifier
Diagnosis specifier (bits 8-10).
Definition diagnosis.h:106
static ChannelProperties FromUint16(std::uint16_t value)
Decode a raw 16-bit ChannelProperties value.
Definition diagnosis.cpp:19
Complete diagnosis data for one slot/subslot.
Definition diagnosis.h:275
bool HasMaintenanceRequired() const
Whether any entry has its maintenance-required flag set.
Definition diagnosis.h:300
bool HasMaintenanceDemanded() const
Whether any entry has its maintenance-demanded flag set.
Definition diagnosis.h:314
std::vector< AnyChannelDiagnosis > entries
Parsed diagnosis entries.
Definition diagnosis.h:286
std::vector< const AnyChannelDiagnosis * > GetByChannel(std::uint16_t channel) const
Find every entry for a specific channel number.
Definition diagnosis.h:329
bool HasErrors() const
Whether any diagnosis entries were found.
Definition diagnosis.h:293
Generic helpers for reading and writing integer and byte data in big- and little-endian wire formats.