2using System.Collections.Generic;
16 private readonly List<ExtendedIdEntry> _entries;
24 _entries = entries?.ToList() ??
new List<ExtendedIdEntry>();
30 public IReadOnlyList<ExtendedIdEntry>
Entries => _entries;
36 public IEnumerable<ExtendedIdEntry>
UnknownEntries => _entries.Where(e => !e.IsKnown);
91 ReadOnlySpan<byte> tlvData = data;
96 ushort offset = (ushort)(data[2] | (data[3] << 8));
97 ushort lengthOfFragment = (ushort)(data[4] | (data[5] << 8));
100 if (data.Length == 6 + lengthOfFragment && offset == 0)
102 tlvData = data.Slice(6);
106 var entries =
new List<ExtendedIdEntry>();
109 while (parseOffset < tlvData.Length)
112 if (entry ==
null || bytesConsumed == 0)
114 if (parseOffset < tlvData.Length)
116 throw new Exception($
"Failed to parse TLV entry at offset {parseOffset}, {tlvData.Length - parseOffset} bytes remaining");
122 parseOffset += bytesConsumed;
132 var tlvData =
new List<byte>();
133 foreach (var entry
in _entries)
135 tlvData.AddRange(entry.BuildData());
143 var wholeMessageLength = (ushort)tlvData.Count;
144 var result =
new List<byte>
147 (byte)(wholeMessageLength & 0xFF),
148 (byte)((wholeMessageLength >> 8) & 0xFF),
155 (byte)(wholeMessageLength & 0xFF),
156 (byte)((wholeMessageLength >> 8) & 0xFF)
160 result.AddRange(tlvData);
162 return result.ToArray();
168 var build =
new StringBuilder();
172 build.AppendLine($
" Manufacturer: {Manufacturer}");
177 build.AppendLine($
" Product Name: {ProductName}");
182 build.AppendLine($
" Serial Number: {SerialNumber}");
186 for (
int i = 0; i < firmwareVersions.Count; i++)
188 var label = i == 0 ?
"Firmware Version" : $
"Firmware Version {i + 1}";
189 build.AppendLine($
"{label,16}: {firmwareVersions[i]}");
194 build.AppendLine($
" Hardware: {HardwareDescription}");
199 build.AppendLine($
" URL: {Url}");
204 build.AppendLine($
" Configuration: {ConfigurationReference}");
209 if (unknownEntries.Any())
211 foreach (var entry
in unknownEntries)
213 build.AppendLine($
" Unknown Tag {entry.TagByte}: {entry.Value}");
217 return build.ToString();
222 return _entries.FirstOrDefault(e => e.Tag == tag)?.Value;
227 return _entries.Where(e => e.Tag == tag).Select(e => e.Value);
Contains standard Security Control Block data that can be used when building messages.
Base class representing a payload an OSDP message.
string Url
Gets the URL, or null if not present.
override ReadOnlySpan< byte > SecurityControlBlock()
string Manufacturer
Gets the manufacturer name, or null if not present.
override string ToString()
string HardwareDescription
Gets the hardware description, or null if not present.
IReadOnlyList< ExtendedIdEntry > Entries
Gets all TLV entries in this identification.
override byte[] BuildData()
string ProductName
Gets the product name, or null if not present.
IEnumerable< ExtendedIdEntry > UnknownEntries
Gets all entries with unknown/undefined tag types.
string ConfigurationReference
Gets the configuration reference, or null if not present.
IEnumerable< string > FirmwareVersions
Gets all firmware version entries.
string SerialNumber
Gets the serial number, or null if not present.
static ExtendedDeviceIdentification ParseData(ReadOnlySpan< byte > data)
Parses the TLV stream from the given data.
ExtendedDeviceIdentification(IEnumerable< ExtendedIdEntry > entries)
Creates a new instance of ExtendedDeviceIdentification with the specified entries.
Represents a single TLV (Tag-Length-Value) entry in the extended device identification response.
static ExtendedIdEntry ParseData(ReadOnlySpan< byte > data, out int bytesConsumed)
Parses a TLV entry from the given data span.
ReplyType
Identifies the type of OSDP protocol reply (PD -> ACU) message.
ExtendedIdTag
Defines the tag types used in the extended device identification TLV stream.