Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
TedsAccessMessage.cs
1using System;
2using System.IO;
3using System.Text;
4using System.Threading.Tasks;
10
12{
17 {
18 private Teds data;
19 private ushort errorCode;
20
33 {
34 this.TedsAccessService = TedsAccessService;
35 }
36
41
45 public override string NetworkServiceIdName => this.TedsAccessService.ToString();
46
51 public Task<(ushort ErrorCode, Teds Teds)> TryParseTeds()
52 {
53 return this.TryParseTeds(true);
54 }
55
61 public async Task<(ushort ErrorCode, Teds Teds)> TryParseTeds(bool CheckChecksum)
62 {
63 if (!(this.data is null))
64 return (this.errorCode, this.data);
65
66 ushort ErrorCode;
67 Teds Teds;
68
69 try
70 {
71 if (this.MessageType == MessageType.Reply)
72 ErrorCode = this.NextUInt16(nameof(ErrorCode));
73 else
74 ErrorCode = 0;
75
76 ChannelAddress ChannelInfo = this.NextChannelId(true);
77 uint TedsOffset = this.NextUInt32(nameof(TedsOffset));
78 int Start = this.Position;
79 uint Len = this.NextUInt32(nameof(Len));
80 if (Len < 2)
81 return (ErrorCode, null);
82
83 Len -= 2;
84 if (Len > int.MaxValue)
85 return (ErrorCode, null);
86
87 byte[] Data = this.NextUInt8Array(nameof(Data), (int)Len);
88 ushort CheckSum = 0;
89
90 while (Start < this.Position)
91 CheckSum += this.Body[Start++];
92
93 CheckSum ^= 0xffff;
94
95 ushort CheckSum2 = this.NextUInt16(nameof(CheckSum));
96 if (CheckChecksum && CheckSum != CheckSum2)
97 return (ErrorCode, null);
98
99 Binary TedsBlock = new Binary(Data, this.ComLayer, true);
100 ParsingState State = new ParsingState();
101
102 this.data = Teds = new Teds(ChannelInfo, TedsBlock.ParseTedsRecords(State));
103 this.errorCode = ErrorCode;
104
105 if (this.HasSniffers)
106 await TedsBlock.LogInformationToSniffer();
107
108 return (ErrorCode, Teds);
109 }
110 catch (Exception ex)
111 {
112 if (this.HasSniffers)
113 await this.ComLayer.Exception(ex);
114
115 return (0xffff, null);
116 }
117 }
118
128 out uint TedsOffset, out double TimeoutSeconds)
129 {
130 try
131 {
132 Channel = this.NextChannelId(true);
133 TedsAccessCode = this.NextUInt8<TedsAccessCode>(nameof(TedsAccessCode));
134 TedsOffset = this.NextUInt32(nameof(TedsOffset));
135 TimeoutSeconds = this.NextTimeDurationSeconds(nameof(TimeoutSeconds));
136
137 return true;
138 }
139 catch (Exception)
140 {
141 Channel = null;
142 TedsAccessCode = 0;
143 TedsOffset = 0;
144 TimeoutSeconds = 0;
145
146 return false;
147 }
148 }
149
161 public static byte[] SerializeRequest(byte[] NcapId, byte[] TimId, ushort ChannelId,
162 TedsAccessCode TedsAccessCode, uint TedsOffset, double TimeoutSeconds, StringBuilder SnifferOutput)
163 {
164 using (MemoryStream ms = new MemoryStream())
165 {
166 byte[] AppId = MeteringTopology.Root.ObjectId.ToByteArray();
167
168 ms.Write(AppId, 0, 16);
169 ms.Write(NcapId ?? EmptyUuid, 0, 16);
170 ms.Write(TimId ?? EmptyUuid, 0, 16);
171 ms.WriteByte((byte)(ChannelId >> 8));
172 ms.WriteByte((byte)ChannelId);
173 ms.WriteByte((byte)TedsAccessCode);
174
175 byte[] Bin = BitConverter.GetBytes(TedsOffset);
176 Array.Reverse(Bin);
177 ms.Write(Bin, 0, 4);
178
179 TimeoutSeconds *= 1e9 * 65536;
180 ulong l = (ulong)TimeoutSeconds;
181 Bin = BitConverter.GetBytes(l);
182 Array.Reverse(Bin);
183 ms.Write(Bin, 0, 8);
184
185 byte[] Result = Ieee1451Parser.SerializeMessage(TedsAccessService.Read, MessageType.Command, ms.ToArray(), SnifferOutput);
186
187 if (!(SnifferOutput is null))
188 {
189 SnifferOutput.Append("App ID: ");
190 SnifferOutput.AppendLine(Hashes.BinaryToString(AppId));
191 SnifferOutput.Append("NCAP ID: ");
192 SnifferOutput.AppendLine(Hashes.BinaryToString(NcapId ?? EmptyUuid));
193 SnifferOutput.Append("TIM ID: ");
194 SnifferOutput.AppendLine(Hashes.BinaryToString(TimId ?? EmptyUuid));
195 SnifferOutput.Append("Channel ID: ");
196 SnifferOutput.AppendLine(ChannelId.ToString());
197 SnifferOutput.Append("TEDS Access Code: ");
198 SnifferOutput.AppendLine(TedsAccessCode.ToString());
199 SnifferOutput.Append("TEDS Offset: ");
200 SnifferOutput.AppendLine(TedsOffset.ToString());
201 SnifferOutput.Append("Timeout (s): ");
202 SnifferOutput.AppendLine(TimeoutSeconds.ToString());
203 }
204
205 return Result;
206 }
207 }
208
220 public static byte[] SerializeResponse(ushort ErrorCode, byte[] NcapId, byte[] TimId,
221 ushort ChannelId, StringBuilder SnifferOutput, TedsId TedsHeader, params TedsRecord[] Records)
222 {
223 if (NcapId is null)
224 NcapId = new byte[16];
225 else if (NcapId.Length != 16)
226 throw new ArgumentException("Invalid NCAP UUID.", nameof(NcapId));
227
228 if (TimId is null)
229 TimId = new byte[16];
230 else if (TimId.Length != 16)
231 throw new ArgumentException("Invalid TIM UUID.", nameof(TimId));
232
233 using (MemoryStream ms = new MemoryStream())
234 {
235 byte[] AppId = MeteringTopology.Root.ObjectId.ToByteArray();
236
237 ms.WriteByte((byte)(ErrorCode >> 8));
238 ms.WriteByte((byte)ErrorCode);
239 ms.Write(AppId, 0, 16);
240 ms.Write(NcapId, 0, 16);
241 ms.Write(TimId, 0, 16);
242 ms.WriteByte((byte)(ChannelId >> 8));
243 ms.WriteByte((byte)ChannelId);
244 ms.WriteByte(0); // TedsOffset MSB
245 ms.WriteByte(0);
246 ms.WriteByte(0);
247 ms.WriteByte(0); // TedsOffset LSB
248
249 using (MemoryStream ms2 = new MemoryStream())
250 {
251 Append(ms2, TedsHeader);
252
253 foreach (TedsRecord Record in Records)
254 Append(ms2, Record);
255
256 byte[] Bin = ms2.ToArray();
257 int Len = Bin.Length;
258 ushort Checksum = 0;
259 int i, j, k;
260 byte b;
261
262 j = Len + 2;
263 k = 0;
264 for (i = 0; i < 4; i++)
265 {
266 k <<= 8;
267 b = (byte)j;
268 k |= b;
269 Checksum += b;
270 j >>= 8;
271 }
272
273 for (i = 0; i < 4; i++)
274 {
275 ms.WriteByte((byte)k);
276 k >>= 8;
277 }
278
279 if (Len > 0)
280 {
281 ms.Write(Bin, 0, Len);
282
283 for (i = 0; i < Len; i++)
284 Checksum += Bin[i];
285 }
286
287 Checksum ^= 0xffff;
288
289 ms.WriteByte((byte)(Checksum >> 8));
290 ms.WriteByte((byte)Checksum);
291
292 byte[] Result = Ieee1451Parser.SerializeMessage(TedsAccessService.Read, MessageType.Reply, ms.ToArray(), SnifferOutput);
293
294 if (!(SnifferOutput is null))
295 {
296 SnifferOutput.Append("Error Code: ");
297 SnifferOutput.AppendLine(ErrorCode.ToString());
298 SnifferOutput.Append("App ID: ");
299 SnifferOutput.AppendLine(Hashes.BinaryToString(AppId));
300 SnifferOutput.Append("NCAP ID: ");
301 SnifferOutput.AppendLine(Hashes.BinaryToString(NcapId));
302 SnifferOutput.Append("TIM ID: ");
303 SnifferOutput.AppendLine(Hashes.BinaryToString(TimId));
304 SnifferOutput.Append("Channel ID: ");
305 SnifferOutput.AppendLine(ChannelId.ToString());
306 SnifferOutput.AppendLine("TEDS Offset: 0");
307
308 TedsHeader.Append(SnifferOutput);
309
310 foreach (TedsRecord Record in Records)
311 Record.Append(SnifferOutput);
312
313 SnifferOutput.AppendLine(Checksum.ToString());
314 SnifferOutput.AppendLine("TEDS Offset: 0");
315 }
316
317 return Result;
318 }
319 }
320 }
321
322 private static void Append(MemoryStream ms2, TedsRecord Record)
323 {
324 byte[] Bin = Record.RawValue;
325 int RecordLen = Bin?.Length ?? 0;
326 if (RecordLen > 255)
327 throw new Exception("Record length exceeds 255 bytes in length.");
328
329 ms2.WriteByte(Record.Type);
330 ms2.WriteByte((byte)RecordLen);
331
332 if (RecordLen > 0)
333 ms2.Write(Bin, 0, RecordLen);
334 }
335 }
336}
Contains methods for simple hash calculations.
Definition: Hashes.cs:59
static string BinaryToString(byte[] Data)
Converts an array of bytes to a string with their hexadecimal representations (in lower case).
Definition: Hashes.cs:65
bool HasSniffers
If sniffers are available.
Definition: Binary.cs:80
ICommunicationLayer ComLayer
Sniffable interface on which the message was received.
Definition: Binary.cs:75
Task LogInformationToSniffer()
Logs accumulated sniffer output to associated sniffable interface.
Definition: Binary.cs:104
uint NextUInt32(string Name)
Gets the next uint.
Definition: Binary.cs:265
TedsRecord[] ParseTedsRecords(ParsingState State)
Parses a set of TEDS records.
Definition: Binary.cs:925
byte[] NextUInt8Array(string Name)
Gets the next Byte array
Definition: Binary.cs:532
double NextTimeDurationSeconds(string Name)
Gets the next time duration, expressed in seconds.
Definition: Binary.cs:480
ushort NextUInt16(string Name)
Gets the next ushort.
Definition: Binary.cs:206
ChannelAddress NextChannelId(bool AppId)
Parses a Channel ID from the message.
static readonly byte[] EmptyUuid
Empty UUID (16 zero bytes)
Definition: Message.cs:13
byte[] Tail
Bytes that are received after the body.
Definition: Message.cs:57
TedsAccessMessage(NetworkServiceType NetworkServiceType, TedsAccessService TedsAccessService, MessageType MessageType, byte[] Body, byte[] Tail, ICommunicationLayer ComLayer)
IEEE 1451.0 TEDS Access Message
override string NetworkServiceIdName
Name of Message.NetworkServiceId
static byte[] SerializeRequest(byte[] NcapId, byte[] TimId, ushort ChannelId, TedsAccessCode TedsAccessCode, uint TedsOffset, double TimeoutSeconds, StringBuilder SnifferOutput)
Serializes a request for TEDS.
async Task<(ushort ErrorCode, Teds Teds)> TryParseTeds(bool CheckChecksum)
Tries to parse a TEDS from the message.
static byte[] SerializeResponse(ushort ErrorCode, byte[] NcapId, byte[] TimId, ushort ChannelId, StringBuilder SnifferOutput, TedsId TedsHeader, params TedsRecord[] Records)
Serializes a response to a TEDS request.
bool TryParseRequest(out ChannelAddress Channel, out TedsAccessCode TedsAccessCode, out uint TedsOffset, out double TimeoutSeconds)
Tries to parse a TEDS request from the message.
Task<(ushort ErrorCode, Teds Teds)> TryParseTeds()
Tries to parse a TEDS from the message.
TEDS identification header (§6.3)
Definition: TedsId.cs:14
Represents one record in a TEDS
Definition: TedsRecord.cs:16
void Append(StringBuilder SnifferOutput)
Appends record to sniffer output.
Definition: TedsRecord.cs:122
Static class for IEEE 1451-related parsing tasks.
static byte[] SerializeMessage(NetworkServiceType NetworkServiceType, byte NetworkServiceId, MessageType MessageType, byte[] Payload)
Creates a binary IEEE 1451.0 message.
Defines the Metering Topology data source. This data source contains a tree structure of persistent r...
Task Exception(string Exception)
Called to inform the viewer of an exception state.
Interface for observable classes implementing communication protocols.
MessageType
Network Service Message Type
Definition: MessageType.cs:7
NetworkServiceType
IEEE 1451.0 Network Service Type
TedsAccessService
TEDS Access Service