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
53 public bool TryParseTeds(out ushort ErrorCode, out Teds Teds)
54 {
55 return this.TryParseTeds(true, out ErrorCode, out Teds);
56 }
57
65 public bool TryParseTeds(bool CheckChecksum, out ushort ErrorCode, out Teds Teds)
66 {
67 if (!(this.data is null))
68 {
69 ErrorCode = this.errorCode;
70 Teds = this.data;
71 return true;
72 }
73
74 try
75 {
76 if (this.MessageType == MessageType.Reply)
77 ErrorCode = this.NextUInt16(nameof(ErrorCode));
78 else
79 ErrorCode = 0;
80
81 ChannelAddress ChannelInfo = this.NextChannelId(true);
82 uint TedsOffset = this.NextUInt32(nameof(TedsOffset));
83 int Start = this.Position;
84 uint Len = this.NextUInt32(nameof(Len));
85 if (Len < 2)
86 {
87 Teds = null;
88 return false;
89 }
90
91 Len -= 2;
92 if (Len > int.MaxValue)
93 {
94 Teds = null;
95 return false;
96 }
97
98 byte[] Data = this.NextUInt8Array(nameof(Data), (int)Len);
99 ushort CheckSum = 0;
100
101 while (Start < this.Position)
102 CheckSum += this.Body[Start++];
103
104 CheckSum ^= 0xffff;
105
106 ushort CheckSum2 = this.NextUInt16(nameof(CheckSum));
107 if (CheckChecksum && CheckSum != CheckSum2)
108 {
109 Teds = null;
110 return false;
111 }
112
113 Binary TedsBlock = new Binary(Data, this.ComLayer, true);
114 ParsingState State = new ParsingState();
115
116 this.data = Teds = new Teds(ChannelInfo, TedsBlock.ParseTedsRecords(State));
117 this.errorCode = ErrorCode;
118
119 if (this.HasSniffers)
120 TedsBlock.LogInformationToSniffer();
121
122 return true;
123 }
124 catch (Exception ex)
125 {
126 if (this.HasSniffers)
127 this.ComLayer.Exception(ex);
128
129 ErrorCode = 0xffff;
130 Teds = null;
131 return false;
132 }
133 }
134
144 out uint TedsOffset, out double TimeoutSeconds)
145 {
146 try
147 {
148 Channel = this.NextChannelId(true);
149 TedsAccessCode = this.NextUInt8<TedsAccessCode>(nameof(TedsAccessCode));
150 TedsOffset = this.NextUInt32(nameof(TedsOffset));
151 TimeoutSeconds = this.NextTimeDurationSeconds(nameof(TimeoutSeconds));
152
153 return true;
154 }
155 catch (Exception)
156 {
157 Channel = null;
158 TedsAccessCode = 0;
159 TedsOffset = 0;
160 TimeoutSeconds = 0;
161
162 return false;
163 }
164 }
165
177 public static byte[] SerializeRequest(byte[] NcapId, byte[] TimId, ushort ChannelId,
178 TedsAccessCode TedsAccessCode, uint TedsOffset, double TimeoutSeconds, StringBuilder SnifferOutput)
179 {
180 using (MemoryStream ms = new MemoryStream())
181 {
182 byte[] AppId = MeteringTopology.Root.ObjectId.ToByteArray();
183
184 ms.Write(AppId, 0, 16);
185 ms.Write(NcapId ?? EmptyUuid, 0, 16);
186 ms.Write(TimId ?? EmptyUuid, 0, 16);
187 ms.WriteByte((byte)(ChannelId >> 8));
188 ms.WriteByte((byte)ChannelId);
189 ms.WriteByte((byte)TedsAccessCode);
190
191 byte[] Bin = BitConverter.GetBytes(TedsOffset);
192 Array.Reverse(Bin);
193 ms.Write(Bin, 0, 4);
194
195 TimeoutSeconds *= 1e9 * 65536;
196 ulong l = (ulong)TimeoutSeconds;
197 Bin = BitConverter.GetBytes(l);
198 Array.Reverse(Bin);
199 ms.Write(Bin, 0, 8);
200
201 byte[] Result = Ieee1451Parser.SerializeMessage(TedsAccessService.Read, MessageType.Command, ms.ToArray(), SnifferOutput);
202
203 if (!(SnifferOutput is null))
204 {
205 SnifferOutput.Append("App ID: ");
206 SnifferOutput.AppendLine(Hashes.BinaryToString(AppId));
207 SnifferOutput.Append("NCAP ID: ");
208 SnifferOutput.AppendLine(Hashes.BinaryToString(NcapId ?? EmptyUuid));
209 SnifferOutput.Append("TIM ID: ");
210 SnifferOutput.AppendLine(Hashes.BinaryToString(TimId ?? EmptyUuid));
211 SnifferOutput.Append("Channel ID: ");
212 SnifferOutput.AppendLine(ChannelId.ToString());
213 SnifferOutput.Append("TEDS Access Code: ");
214 SnifferOutput.AppendLine(TedsAccessCode.ToString());
215 SnifferOutput.Append("TEDS Offset: ");
216 SnifferOutput.AppendLine(TedsOffset.ToString());
217 SnifferOutput.Append("Timeout (s): ");
218 SnifferOutput.AppendLine(TimeoutSeconds.ToString());
219 }
220
221 return Result;
222 }
223 }
224
236 public static byte[] SerializeResponse(ushort ErrorCode, byte[] NcapId, byte[] TimId,
237 ushort ChannelId, StringBuilder SnifferOutput, TedsId TedsHeader, params TedsRecord[] Records)
238 {
239 if (NcapId is null)
240 NcapId = new byte[16];
241 else if (NcapId.Length != 16)
242 throw new ArgumentException("Invalid NCAP UUID.", nameof(NcapId));
243
244 if (TimId is null)
245 TimId = new byte[16];
246 else if (TimId.Length != 16)
247 throw new ArgumentException("Invalid TIM UUID.", nameof(TimId));
248
249 using (MemoryStream ms = new MemoryStream())
250 {
251 byte[] AppId = MeteringTopology.Root.ObjectId.ToByteArray();
252
253 ms.WriteByte((byte)(ErrorCode >> 8));
254 ms.WriteByte((byte)ErrorCode);
255 ms.Write(AppId, 0, 16);
256 ms.Write(NcapId, 0, 16);
257 ms.Write(TimId, 0, 16);
258 ms.WriteByte((byte)(ChannelId >> 8));
259 ms.WriteByte((byte)ChannelId);
260 ms.WriteByte(0); // TedsOffset MSB
261 ms.WriteByte(0);
262 ms.WriteByte(0);
263 ms.WriteByte(0); // TedsOffset LSB
264
265 using (MemoryStream ms2 = new MemoryStream())
266 {
267 Append(ms2, TedsHeader);
268
269 foreach (TedsRecord Record in Records)
270 Append(ms2, Record);
271
272 byte[] Bin = ms2.ToArray();
273 int Len = Bin.Length;
274 ushort Checksum = 0;
275 int i, j, k;
276 byte b;
277
278 j = Len + 2;
279 k = 0;
280 for (i = 0; i < 4; i++)
281 {
282 k <<= 8;
283 b = (byte)j;
284 k |= b;
285 Checksum += b;
286 j >>= 8;
287 }
288
289 for (i = 0; i < 4; i++)
290 {
291 ms.WriteByte((byte)k);
292 k >>= 8;
293 }
294
295 if (Len > 0)
296 {
297 ms.Write(Bin, 0, Len);
298
299 for (i = 0; i < Len; i++)
300 Checksum += Bin[i];
301 }
302
303 Checksum ^= 0xffff;
304
305 ms.WriteByte((byte)(Checksum >> 8));
306 ms.WriteByte((byte)Checksum);
307
308 byte[] Result = Ieee1451Parser.SerializeMessage(TedsAccessService.Read, MessageType.Reply, ms.ToArray(), SnifferOutput);
309
310 if (!(SnifferOutput is null))
311 {
312 SnifferOutput.Append("Error Code: ");
313 SnifferOutput.AppendLine(ErrorCode.ToString());
314 SnifferOutput.Append("App ID: ");
315 SnifferOutput.AppendLine(Hashes.BinaryToString(AppId));
316 SnifferOutput.Append("NCAP ID: ");
317 SnifferOutput.AppendLine(Hashes.BinaryToString(NcapId));
318 SnifferOutput.Append("TIM ID: ");
319 SnifferOutput.AppendLine(Hashes.BinaryToString(TimId));
320 SnifferOutput.Append("Channel ID: ");
321 SnifferOutput.AppendLine(ChannelId.ToString());
322 SnifferOutput.AppendLine("TEDS Offset: 0");
323
324 TedsHeader.Append(SnifferOutput);
325
326 foreach (TedsRecord Record in Records)
327 Record.Append(SnifferOutput);
328
329 SnifferOutput.AppendLine(Checksum.ToString());
330 SnifferOutput.AppendLine("TEDS Offset: 0");
331 }
332
333 return Result;
334 }
335 }
336 }
337
338 private static void Append(MemoryStream ms2, TedsRecord Record)
339 {
340 byte[] Bin = Record.RawValue;
341 int RecordLen = Bin?.Length ?? 0;
342 if (RecordLen > 255)
343 throw new Exception("Record length exceeds 255 bytes in length.");
344
345 ms2.WriteByte(Record.Type);
346 ms2.WriteByte((byte)RecordLen);
347
348 if (RecordLen > 0)
349 ms2.Write(Bin, 0, RecordLen);
350 }
351 }
352}
Contains methods for simple hash calculations.
Definition: Hashes.cs:57
static string BinaryToString(byte[] Data)
Converts an array of bytes to a string with their hexadecimal representations (in lower case).
Definition: Hashes.cs:63
void LogInformationToSniffer()
Logs accumulated sniffer output to associated sniffable interface.
Definition: Binary.cs:104
bool HasSniffers
If sniffers are available.
Definition: Binary.cs:80
ICommunicationLayer ComLayer
Sniffable interface on which the message was received.
Definition: Binary.cs:75
uint NextUInt32(string Name)
Gets the next uint.
Definition: Binary.cs:263
TedsRecord[] ParseTedsRecords(ParsingState State)
Parses a set of TEDS records.
Definition: Binary.cs:923
byte[] NextUInt8Array(string Name)
Gets the next Byte array
Definition: Binary.cs:530
double NextTimeDurationSeconds(string Name)
Gets the next time duration, expressed in seconds.
Definition: Binary.cs:478
ushort NextUInt16(string Name)
Gets the next ushort.
Definition: Binary.cs:204
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
bool TryParseTeds(bool CheckChecksum, out ushort ErrorCode, out Teds Teds)
Tries to parse a TEDS from the message.
static byte[] SerializeRequest(byte[] NcapId, byte[] TimId, ushort ChannelId, TedsAccessCode TedsAccessCode, uint TedsOffset, double TimeoutSeconds, StringBuilder SnifferOutput)
Serializes a request for TEDS.
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.
bool TryParseTeds(out ushort ErrorCode, out Teds Teds)
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...
void 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