Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
UPnPStateVariable.cs
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Threading.Tasks;
5using System.Xml;
6using Waher.Content;
7
9{
13 public class UPnPStateVariable
14 {
15 private readonly XmlElement xml;
16 private readonly string[] allowedValues;
17 private readonly string name;
18 private readonly string dataType;
19 private readonly string defaultValue;
20 private readonly string minimum;
21 private readonly string maximum;
22 private readonly string step;
23 private readonly bool sendsEvents;
24 private readonly bool hasAllowedValues = false;
25 private readonly bool hasAllowedValueRange = false;
26
27 internal UPnPStateVariable(XmlElement Xml)
28 {
29 List<string> AllowedValues = new List<string>();
30
31 this.xml = Xml;
32
33 this.sendsEvents = (Xml.HasAttribute("sendEvents") && Xml.GetAttribute("sendEvents") == "yes");
34
35 foreach (XmlNode N in Xml.ChildNodes)
36 {
37 switch (N.LocalName)
38 {
39 case "name":
40 this.name = N.InnerText;
41 break;
42
43 case "dataType":
44 this.dataType = N.InnerText;
45 break;
46
47 case "defaultValue":
48 this.defaultValue = N.InnerText;
49 break;
50
51 case "allowedValueList":
52 this.hasAllowedValues = true;
53 foreach (XmlNode N2 in N.ChildNodes)
54 {
55 if (N2.LocalName == "allowedValue")
56 AllowedValues.Add(N2.InnerText);
57 }
58 break;
59
60 case "allowedValueRange":
61 this.hasAllowedValueRange = true;
62 foreach (XmlNode N2 in N.ChildNodes)
63 {
64 switch (N2.LocalName)
65 {
66 case "minimum":
67 this.minimum = N2.InnerText;
68 break;
69
70 case "maximum":
71 this.maximum = N2.InnerText;
72 break;
73
74 case "step":
75 this.step = N2.InnerText;
76 break;
77 }
78 }
79 break;
80 }
81 }
82
83 this.allowedValues = AllowedValues.ToArray();
84 }
85
89 public XmlElement Xml => this.xml;
90
94 public string Name => this.name;
95
99 public string DataType => this.dataType;
100
104 public string DefaultValue => this.defaultValue;
105
109 public bool SendsEvents => this.sendsEvents;
110
114 public string[] AllowedValues => this.allowedValues;
115
119 public bool HasAllowedValues => this.hasAllowedValues;
120
124 public bool HasAllowedValueRange => this.hasAllowedValueRange;
125
129 public string Minimum => this.minimum;
130
134 public string Maximum => this.maximum;
135
139 public string Step => this.step;
140
146 public async Task<string> ValueToXmlString(object Value)
147 {
148 switch (this.dataType)
149 {
150 case "ui1":
151 case "ui2":
152 case "ui4":
153 case "i1":
154 case "i2":
155 case "i4":
156 case "int":
157 case "char":
158 case "string":
159 case "uri":
160 case "uuid":
161 default:
162 return Value.ToString();
163
164 case "r4":
165 case "r8":
166 case "number":
167 case "float":
168 if (!(Value is double d))
169 {
170 if (Value is float f)
171 d = f;
172 else if (Value is decimal dec)
173 d = (double)dec;
174 else
175 d = Convert.ToDouble(Value);
176 }
177
178 return d.ToString().Replace(System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, ".");
179
180 case "fixed.14.4":
181
182 if (Value is double d2)
183 d = d2;
184 else if (Value is float f2)
185 d = f2;
186 else if (Value is decimal dec2)
187 d = (double)dec2;
188 else
189 d = Convert.ToDouble(Value);
190
191 return d.ToString("F4").Replace(System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, ".");
192
193 case "date":
194 if (!(Value is DateTime DT))
195 DT = Convert.ToDateTime(Value);
196
197 return DT.ToString("yyyyMMdd");
198
199 case "dateTime":
200 if (!(Value is DateTime DT2))
201 DT2 = Convert.ToDateTime(Value);
202
203 return DT2.ToString("yyyyMMddTHHmmss");
204
205 case "dateTime.tz":
206 if (Value is DateTimeOffset DTO)
207 {
208 string s = DTO.ToString("yyyyMMddTHHmmss");
209 TimeSpan Zone = DTO.Offset;
210
211 if (Zone < TimeSpan.Zero)
212 {
213 s += "-";
214 Zone = -Zone;
215 }
216 else
217
218 s += "+";
219
220 return s + Zone.Hours.ToString("D2") + ":" + Zone.Minutes.ToString("D2");
221 }
222 else
223 {
224 if (!(Value is DateTime DT3))
225 DT3 = Convert.ToDateTime(Value);
226
227 return DT3.ToString("yyyyMMddTHHmmss");
228 }
229
230 case "time":
231 if (Value is TimeSpan TS)
232 return TS.Hours.ToString("D2") + ":" + TS.Minutes.ToString("D2") + ":" + TS.Seconds.ToString("D2");
233 else if (Value is DateTime DT4)
234 return DT4.ToString("HH:mm:ss");
235 else if (TimeSpan.TryParse(Value.ToString(), out TS))
236 return TS.Hours.ToString("D2") + ":" + TS.Minutes.ToString("D2") + ":" + TS.Seconds.ToString("D2");
237 else
238 {
239 DT = Convert.ToDateTime(Value);
240 return DT.ToString("HH:mm:ss");
241 }
242
243 case "time.tz":
244 if (Value is TimeSpan TS2)
245 return TS2.Hours.ToString("D2") + ":" + TS2.Minutes.ToString("D2") + ":" + TS2.Seconds.ToString("D2");
246 else if (Value is DateTime DT5)
247 return DT5.ToString("HH:mm:ss");
248 else if (Value is DateTimeOffset DTO2)
249 {
250 string s = DTO2.ToString("HH:mm:ss");
251 TimeSpan Zone = DTO2.Offset;
252
253 if (Zone < TimeSpan.Zero)
254 {
255 s += "-";
256 Zone = -Zone;
257 }
258 else
259
260 s += "+";
261
262 return s + Zone.Hours.ToString("D2") + ":" + Zone.Minutes.ToString("D2");
263 }
264 else if (TimeSpan.TryParse(Value.ToString(), out TS))
265 return TS.Hours.ToString("D2") + ":" + TS.Minutes.ToString("D2") + ":" + TS.Seconds.ToString("D2");
266 else
267 {
268 DT = Convert.ToDateTime(Value);
269 return DT.ToString("HH:mm:ss");
270 }
271
272 case "boolean":
273 if (!(Value is bool b))
274 b = Convert.ToBoolean(Value);
275
276 return b ? "1" : "0";
277
278 case "bin.base64":
279 if (!(Value is byte[] Bin))
280 Bin = await SerializeToBinary(Value);
281
282 return Convert.ToBase64String(Bin);
283
284 case "bin.hex":
285 if (!(Value is byte[] Bin2))
286 Bin2 = await SerializeToBinary(Value);
287
288 StringBuilder sb = new StringBuilder();
289
290 foreach (byte b2 in Bin2)
291 sb.Append(b2.ToString("X2"));
292
293 return sb.ToString();
294 }
295 }
296
302 public object XmlStringToValue(string Value)
303 {
304 switch (this.dataType)
305 {
306 case "ui1":
307 return byte.Parse(Value);
308
309 case "ui2":
310 return ushort.Parse(Value);
311
312 case "ui4":
313 return uint.Parse(Value);
314
315 case "i1":
316 return sbyte.Parse(Value);
317
318 case "i2":
319 return short.Parse(Value);
320
321 case "i4":
322 return int.Parse(Value);
323
324 case "int":
325 return long.Parse(Value);
326
327 case "char":
328 return Value[0];
329
330 case "string":
331 return Value;
332
333 case "uri":
334 return new Uri(Value);
335
336 case "uuid":
337 return new Guid(Value);
338
339 case "r4":
340 return float.Parse(Value.Replace(".", System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator));
341
342 case "r8":
343 case "number":
344 case "float":
345 case "fixed.14.4":
346 return double.Parse(Value.Replace(".", System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator));
347
348 case "date":
349 return DateTime.Parse(Value);
350
351 case "dateTime":
352 return DateTime.Parse(Value.Replace("T", " "));
353
354 case "dateTime.tz":
355 return DateTimeOffset.Parse(Value.Replace("T", " "));
356
357 case "time":
358 case "time.tz":
359 return TimeSpan.Parse(Value.Replace("T", " "));
360
361 case "boolean":
362 Value = Value.ToLower();
363 return (Value == "1" || Value == "true" || Value == "yes");
364
365 case "bin.base64":
366 return Convert.FromBase64String(Value);
367
368 case "bin.hex":
369 int i, c = Value.Length;
370 if ((c & 1) == 1)
371 throw new Exception("Invalid bin.hex value");
372
373 byte[] Bin = new byte[c / 2];
374 int j;
375 byte b;
376 char ch;
377
378 for (i = j = 0; i < c;)
379 {
380 ch = Value[i++];
381
382 if (ch >= '0' && ch <= '9')
383 b = (byte)(ch - '0');
384 else if (ch >= 'A' && ch <= 'F')
385 b = (byte)(ch - 'A' + 10);
386 else if (ch >= 'a' && ch <= 'f')
387 b = (byte)(ch - 'a' + 10);
388 else
389 throw new Exception("Invalid bin.hex value");
390
391 b <<= 4;
392 ch = Value[i++];
393
394 if (ch >= '0' && ch <= '9')
395 b |= (byte)(ch - '0');
396 else if (ch >= 'A' && ch <= 'F')
397 b |= (byte)(ch - 'A' + 10);
398 else if (ch >= 'a' && ch <= 'f')
399 b |= (byte)(ch - 'a' + 10);
400 else
401 throw new Exception("Invalid bin.hex value");
402
403 Bin[j++] = b;
404 }
405
406 return Bin;
407
408 default:
409 return Value;
410 }
411 }
412
418 public static async Task<byte[]> SerializeToBinary(object Value)
419 {
420 if (Value is byte[] Bin)
421 return Bin;
422 else
423 {
424 KeyValuePair<byte[], string> P = await InternetContent.EncodeAsync(Value, Encoding.UTF8);
425 return P.Key;
426 }
427 }
428 }
429}
Static class managing encoding and decoding of internet content.
static Task< KeyValuePair< byte[], string > > EncodeAsync(object Object, Encoding Encoding, params string[] AcceptedContentTypes)
Encodes an object.
Contains information about a state variable.
static async Task< byte[]> SerializeToBinary(object Value)
Serializes an object to an array of bytes.
string Minimum
Smallest value allowed. Provided if HasAllowedValueRange is true.
bool HasAllowedValueRange
If Minimum, Maximum and Step defines a range of allowed values.
object XmlStringToValue(string Value)
Converts a value from its XML string representation to an object value with the correct type.
string Maximum
Largest value allowed. Provided if HasAllowedValueRange is true.
XmlElement Xml
Underlying XML definition.
bool HasAllowedValues
If AllowedValues contains a list of allowed values.
async Task< string > ValueToXmlString(object Value)
Converts a value to its XML string representation.
bool SendsEvents
If state variable sends events.
string Step
Step value. Provided if HasAllowedValueRange is true.
string[] AllowedValues
List of allowed values. Provided if HasAllowedValues is true.