| Name | Message | Date |
|---|---|---|
| 📄 ExtendedHeader.cs | 1 month ago | |
| 📄 MessageEnums.cs | 1 month ago | |
| 📄 StandardHeader.cs | 1 month ago | |
| 📄 StorageHeader.cs | 1 month ago |
📄
src/Headers/StandardHeader.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
using System.Buffers.Binary; using SharpDlt.Internal; namespace SharpDlt; /// <summary> /// The Standard Header of a DLT message. /// </summary> /// <param name="UseExtendedHeader">If set, the Extended Header is transmitted.</param> /// <param name="MsbFirst">If set, the payload data is big endian, otherwise little endian.</param> /// <param name="VersionNumber">Version number of the DLT data protocol.</param> /// <param name="MessageCounter">Continuous number of the message.</param> /// <param name="Length">Length of the complete message (without Storage Header) in bytes.</param> /// <param name="EcuId">Unique address of the sender, if transmitted.</param> /// <param name="SessionId">Session number, if transmitted.</param> /// <param name="Timestamp">Ticks of the ECU at the moment the message was sent, if transmitted.</param> public sealed record StandardHeader( bool UseExtendedHeader, bool MsbFirst, int VersionNumber, byte MessageCounter, ushort Length, string? EcuId = null, uint? SessionId = null, uint? Timestamp = null ) { /// <summary>Minimum length of the Standard Header in bytes.</summary> public const int MinimumLength = 4; private const byte UseExtendedHeaderMask = 0b0000_0001; private const byte MsbFirstMask = 0b0000_0010; private const byte WithEcuIdMask = 0b0000_0100; private const byte WithSessionIdMask = 0b0000_1000; private const byte WithTimestampMask = 0b0001_0000; private const byte VersionNumberMask = 0b1110_0000; private const int VersionNumberShift = 5; /// <summary>Gets a value indicating whether the header carries an ECU ID.</summary> public bool WithEcuId => EcuId is not null; /// <summary>Gets a value indicating whether the header carries a session ID.</summary> public bool WithSessionId => SessionId is not null; /// <summary>Gets a value indicating whether the header carries a timestamp.</summary> public bool WithTimestamp => Timestamp is not null; /// <summary>Gets the length of this header in bytes.</summary> public int ByteLength => MinimumLength + (WithEcuId ? 4 : 0) + (WithSessionId ? 4 : 0) + (WithTimestamp ? 4 : 0); /// <summary>Gets the Header Type (HTYP) byte.</summary> public byte HeaderType { get { var htyp = (VersionNumber << VersionNumberShift) & VersionNumberMask; if (UseExtendedHeader) { htyp |= UseExtendedHeaderMask; } if (MsbFirst) { htyp |= MsbFirstMask; } if (WithEcuId) { htyp |= WithEcuIdMask; } if (WithSessionId) { htyp |= WithSessionIdMask; } if (WithTimestamp) { htyp |= WithTimestampMask; } return (byte)htyp; } } /// <summary> /// Reads the message length field of a Standard Header which starts at the beginning of /// <paramref name="data"/>. /// </summary> /// <exception cref="DltParseException">The data is shorter than the minimum header length.</exception> public static ushort ReadMessageLength(ReadOnlySpan<byte> data) { if (data.Length < MinimumLength) { throw new DltParseException( $"Unexpected length of the data: {data.Length} / Standard Header must be {MinimumLength} or more." ); } return BinaryPrimitives.ReadUInt16BigEndian(data[2..]); } /// <summary>Parses a Standard Header from the beginning of <paramref name="data"/>.</summary> /// <exception cref="DltParseException">The data is too short for the encoded header type.</exception> public static StandardHeader Parse(ReadOnlySpan<byte> data) { if (data.Length < MinimumLength) { throw new DltParseException( $"Unexpected length of the data: {data.Length} / Standard Header must be {MinimumLength} or more." ); } var headerType = data[0]; var useExtendedHeader = (headerType & UseExtendedHeaderMask) != 0; var msbFirst = (headerType & MsbFirstMask) != 0; var withEcuId = (headerType & WithEcuIdMask) != 0; var withSessionId = (headerType & WithSessionIdMask) != 0; var withTimestamp = (headerType & WithTimestampMask) != 0; var versionNumber = (headerType & VersionNumberMask) >> VersionNumberShift; var expectedLength = MinimumLength + (withEcuId ? 4 : 0) + (withSessionId ? 4 : 0) + (withTimestamp ? 4 : 0); if (data.Length < expectedLength) { throw new DltParseException( $"Unexpected length of the data: {data.Length} / Standard Header with Header Type: " + $"WEID={withEcuId} WSID={withSessionId} WTMS={withTimestamp} " + $"must be {expectedLength} or more." ); } var messageCounter = data[1]; var length = BinaryPrimitives.ReadUInt16BigEndian(data[2..]); var offset = MinimumLength; string? ecuId = null; if (withEcuId) { ecuId = AsciiText.Decode(data.Slice(offset, 4)); offset += 4; } uint? sessionId = null; if (withSessionId) { sessionId = BinaryPrimitives.ReadUInt32BigEndian(data[offset..]); offset += 4; } uint? timestamp = null; if (withTimestamp) { timestamp = BinaryPrimitives.ReadUInt32BigEndian(data[offset..]); } return new StandardHeader( useExtendedHeader, msbFirst, versionNumber, messageCounter, length, ecuId, sessionId, timestamp ); } }