Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
VirtualNode.cs
1using System;
3using System.Threading.Tasks;
4using Waher.Content;
6using Waher.Events;
15using Waher.Script;
21
23{
28 {
29 private static Scheduler scheduler = null;
30
31 private readonly Dictionary<string, SensorData.Field> fields = new Dictionary<string, SensorData.Field>();
32 private List<SensorData.Field> toReport = null;
33 private DateTime nextReport = DateTime.MinValue;
34 private bool hasReport = false;
35
39 public VirtualNode()
40 : base()
41 {
42 }
43
47 public MetaDataValue[] MetaData { get; set; }
48
54 public override Task<string> GetTypeNameAsync(Language Language)
55 {
56 return Language.GetStringAsync(typeof(VirtualNode), 1, "Virtual Node");
57 }
58
64 public override async Task<bool> AcceptsChildAsync(INode Child)
65 {
66 return Child is VirtualNode || await Child.AcceptsParentAsync(this);
67 }
68
74 public override Task<bool> AcceptsParentAsync(INode Parent)
75 {
76 return Task.FromResult(
77 Parent is Root ||
80 }
81
86 public override async Task AnnotatePropertyForm(FormState Form)
87 {
88 await base.AnnotatePropertyForm(Form);
89
90 if ((this.MetaData?.Length ?? 0) > 0)
91 {
94 string PageLabel = await Namespace.GetStringAsync(2, "Meta-data");
95 string ExternalDescription = await Namespace.GetStringAsync(3, "Meta-data value is defined by external source.");
96 Page MetaDataPage = new Page(Form.Form, PageLabel)
97 {
98 Ordinal = Form.PageOrdinal++
99 };
100 Field Field;
101
102 Form.Pages.Add(MetaDataPage);
103 Form.PageByLabel[PageLabel] = MetaDataPage;
104
105 foreach (MetaDataValue Tag in this.MetaData)
106 {
107 if (Tag.Value is string s)
108 {
109 Field = new TextSingleField(Form.Form, Tag.Name, Tag.Name, false,
110 new string[] { s }, null, ExternalDescription, new StringDataType(),
111 null, null, false, false, false);
112 }
113 else if (Tag.Value is int i)
114 {
115 Field = new TextSingleField(Form.Form, Tag.Name, Tag.Name, false,
116 new string[] { i.ToString() }, null, ExternalDescription, new IntegerDataType(),
117 null, null, false, false, false);
118 }
119 else if (Tag.Value is long l)
120 {
121 Field = new TextSingleField(Form.Form, Tag.Name, Tag.Name, false,
122 new string[] { l.ToString() }, null, ExternalDescription, new LongDataType(),
123 null, null, false, false, false);
124 }
125 else if (Tag.Value is short sh)
126 {
127 Field = new TextSingleField(Form.Form, Tag.Name, Tag.Name, false,
128 new string[] { sh.ToString() }, null, ExternalDescription, new ShortDataType(),
129 null, null, false, false, false);
130 }
131 else if (Tag.Value is byte b2)
132 {
133 Field = new TextSingleField(Form.Form, Tag.Name, Tag.Name, false,
134 new string[] { b2.ToString() }, null, ExternalDescription, new ByteDataType(),
135 null, null, false, false, false);
136 }
137 else if (Tag.Value is double d)
138 {
139 Field = new TextSingleField(Form.Form, Tag.Name, Tag.Name, false,
140 new string[] { CommonTypes.Encode(d) }, null, ExternalDescription, new DoubleDataType(),
141 null, null, false, false, false);
142 }
143 else if (Tag.Value is decimal d2)
144 {
145 Field = new TextSingleField(Form.Form, Tag.Name, Tag.Name, false,
146 new string[] { CommonTypes.Encode(d2) }, null, ExternalDescription, new DecimalDataType(),
147 null, null, false, false, false);
148 }
149 else if (Tag.Value is bool b)
150 {
151 Field = new TextSingleField(Form.Form, Tag.Name, Tag.Name, false,
152 new string[] { CommonTypes.Encode(b) }, null, ExternalDescription, new BooleanDataType(),
153 null, null, false, false, false);
154 }
155 else if (Tag.Value is TimeSpan TS)
156 {
157 Field = new TextSingleField(Form.Form, Tag.Name, Tag.Name, false,
158 new string[] { TS.ToString() }, null, ExternalDescription, new TimeDataType(),
159 null, null, false, false, false);
160 }
161 else if (Tag.Value is DateTime TP)
162 {
163 Field = new TextSingleField(Form.Form, Tag.Name, Tag.Name, false,
164 new string[] { XML.Encode(TP) }, null, ExternalDescription, new DateTimeDataType(),
165 null, null, false, false, false);
166 }
167 else if (Tag.Value is Uri Uri)
168 {
169 Field = new TextSingleField(Form.Form, Tag.Name, Tag.Name, false,
170 new string[] { Uri.ToString() }, null, ExternalDescription, new AnyUriDataType(),
171 null, null, false, false, false);
172 }
173 else if (Tag.Value is string[] Rows)
174 {
175 Field = new TextMultiField(Form.Form, Tag.Name, Tag.Name, false,
176 Rows, null, ExternalDescription, null, null, null, false, false, false);
177 }
178 else
179 {
180 Field = new TextSingleField(Form.Form, Tag.Name, Tag.Name, false,
181 new string[] { Tag.Value?.ToString() ?? string.Empty }, null, ExternalDescription, null,
182 null, null, false, false, false);
183 }
184
185 Field.Ordinal = Form.FieldOrdinal++;
186 Form.Fields.Add(Field);
187 MetaDataPage.Add(new FieldReference(Form.Form, Field.Var));
188 }
189 }
190 }
191
198 public bool TryGetMetaDataValue(string Name, out object Value)
199 {
200 if (this.metaDataByName is null)
201 this.BuildDictionary();
202
203 if (this.metaDataByName.TryGetValue(Name, out MetaDataValue Tag))
204 {
205 Value = Tag.Value;
206 return true;
207 }
208 else
209 {
210 Value = null;
211 return false;
212 }
213 }
214
215 private void BuildDictionary()
216 {
217 SortedDictionary<string, MetaDataValue> ByName = new SortedDictionary<string, MetaDataValue>();
218
219 if (!(this.MetaData is null))
220 {
221 foreach (MetaDataValue P in this.MetaData)
222 ByName[P.Name] = P;
223 }
224
225 this.metaDataByName = ByName;
226 }
227
228 private SortedDictionary<string, MetaDataValue> metaDataByName = null;
229
235 {
236 if (this.TryGetMetaDataValue(Field.Var, out object Prev))
237 {
238 try
239 {
240 if (Prev is string)
241 return Task.CompletedTask;
242 else if (Prev is int)
243 {
244 if (!int.TryParse(Field.ValueString, out _))
245 Field.Error = "Value must be a valid integer.";
246 }
247 else if (Prev is long)
248 {
249 if (!long.TryParse(Field.ValueString, out _))
250 Field.Error = "Value must be a valid long integer.";
251 }
252 else if (Prev is short)
253 {
254 if (!short.TryParse(Field.ValueString, out _))
255 Field.Error = "Value must be a valid short integer.";
256 }
257 else if (Prev is byte)
258 {
259 if (!byte.TryParse(Field.ValueString, out _))
260 Field.Error = "Value must be a valid byte.";
261 }
262 else if (Prev is double)
263 {
264 if (!CommonTypes.TryParse(Field.ValueString, out double _))
265 Field.Error = "Value must be a valid double-precision floating-point value.";
266 }
267 else if (Prev is decimal)
268 {
269 if (!CommonTypes.TryParse(Field.ValueString, out decimal _))
270 Field.Error = "Value must be a valid decimal-precision floating-point value.";
271 }
272 else if (Prev is bool)
273 {
274 if (!CommonTypes.TryParse(Field.ValueString, out bool _))
275 Field.Error = "Value must be a valid boolean value.";
276 }
277 else if (Prev is TimeSpan)
278 {
279 if (!TimeSpan.TryParse(Field.ValueString, out _))
280 Field.Error = "Value must be a valid TimeSpan value.";
281 }
282 else if (Prev is DateTime)
283 {
284 if (!XML.TryParse(Field.ValueString, out DateTime _))
285 Field.Error = "Value must be a valid DateTime value.";
286 }
287 else if (Prev is Uri)
288 {
289 if (!Uri.TryCreate(Field.ValueString, UriKind.Absolute, out _))
290 Field.Error = "Value must be a valid URI value.";
291 }
292 else if (Prev is string[])
293 {
294 return Task.CompletedTask;
295 }
296 else
297 {
298 return Task.CompletedTask;
299 }
300 }
301 catch (Exception ex)
302 {
303 ex = Log.UnnestException(ex);
304 Field.Error = ex.Message;
305 }
306 }
307
308 return Task.CompletedTask;
309 }
310
316 {
317 if (this.metaDataByName is null)
318 this.BuildDictionary();
319
320 if (this.metaDataByName.TryGetValue(Field.Var, out MetaDataValue Prev))
321 {
322 try
323 {
324 if (Prev.Value is string)
325 Prev.Value = Field.ValueString;
326 else if (Prev.Value is int)
327 {
328 if (int.TryParse(Field.ValueString, out int i))
329 Prev.Value = i;
330 }
331 else if (Prev.Value is long)
332 {
333 if (long.TryParse(Field.ValueString, out long l))
334 Prev.Value = l;
335 }
336 else if (Prev.Value is short)
337 {
338 if (short.TryParse(Field.ValueString, out short sh))
339 Field.Error = "Value must be a valid short integer.";
340 }
341 else if (Prev.Value is byte)
342 {
343 if (byte.TryParse(Field.ValueString, out byte b))
344 Prev.Value = b;
345 }
346 else if (Prev.Value is double)
347 {
348 if (CommonTypes.TryParse(Field.ValueString, out double d))
349 Prev.Value = d;
350 }
351 else if (Prev.Value is decimal)
352 {
353 if (CommonTypes.TryParse(Field.ValueString, out decimal d))
354 Prev.Value = d;
355 }
356 else if (Prev.Value is bool)
357 {
358 if (CommonTypes.TryParse(Field.ValueString, out bool b))
359 Prev.Value = b;
360 }
361 else if (Prev.Value is TimeSpan)
362 {
363 if (TimeSpan.TryParse(Field.ValueString, out TimeSpan TS))
364 Prev.Value = TS;
365 }
366 else if (Prev.Value is DateTime)
367 {
368 if (XML.TryParse(Field.ValueString, out DateTime TP))
369 Prev.Value = TP;
370 }
371 else if (Prev.Value is Uri)
372 {
373 if (Uri.TryCreate(Field.ValueString, UriKind.Absolute, out Uri Url))
374 Prev.Value = Url;
375 }
376 else if (Prev.Value is string[])
377 Prev.Value = Field.ValueStrings;
378 else
379 Prev.Value = Field.ValueString;
380 }
381 catch (Exception ex)
382 {
383 ex = Log.UnnestException(ex);
384 Field.Error = ex.Message;
385 }
386 }
387 else
388 this.SetMetaDataPriv(Field.Var, Field.ValueString);
389
390 return Task.CompletedTask;
391 }
392
398 public object GetMetaData(string Name)
399 {
400 if (this.TryGetMetaDataValue(Name, out object Value))
401 return Value;
402 else
403 return null;
404 }
405
411 public async Task SetMetaData(string Name, object Value)
412 {
413 if (this.metaDataByName is null)
414 this.BuildDictionary();
415
416 if (this.metaDataByName.TryGetValue(Name, out MetaDataValue Tag))
417 Tag.Value = Value;
418 else
419 this.SetMetaDataPriv(Name, Value);
420
421 await this.UpdateAsync();
422 }
423
424 private void SetMetaDataPriv(string Name, object Value)
425 {
426 this.metaDataByName[Name] = new MetaDataValue()
427 {
428 Name = Name,
429 Value = Value
430 };
431
432 MetaDataValue[] Values = new MetaDataValue[this.metaDataByName.Count];
433 this.metaDataByName.Values.CopyTo(Values, 0);
434 this.MetaData = Values;
435 }
436
443 public override async Task<IEnumerable<Parameter>> GetDisplayableParametersAsync(Language Language, RequestOrigin Caller)
444 {
445 LinkedList<Parameter> Result = await base.GetDisplayableParametersAsync(Language, Caller) as LinkedList<Parameter>;
446
447 if (!(this.MetaData is null))
448 {
449 foreach (MetaDataValue Tag in this.MetaData)
450 {
451 if (Tag.Value is string s)
452 Result.AddLast(new StringParameter(Tag.Name, Tag.Name, s));
453 else if (Tag.Value is int i)
454 Result.AddLast(new Int32Parameter(Tag.Name, Tag.Name, i));
455 else if (Tag.Value is long l)
456 Result.AddLast(new Int64Parameter(Tag.Name, Tag.Name, l));
457 else if (Tag.Value is short sh)
458 Result.AddLast(new Int32Parameter(Tag.Name, Tag.Name, sh));
459 else if (Tag.Value is byte b)
460 Result.AddLast(new Int32Parameter(Tag.Name, Tag.Name, b));
461 else if (Tag.Value is double d)
462 Result.AddLast(new DoubleParameter(Tag.Name, Tag.Name, d));
463 else if (Tag.Value is decimal d2)
464 Result.AddLast(new DoubleParameter(Tag.Name, Tag.Name, (double)d2));
465 else if (Tag.Value is bool b2)
466 Result.AddLast(new BooleanParameter(Tag.Name, Tag.Name, b2));
467 else if (Tag.Value is TimeSpan TS)
468 Result.AddLast(new TimeSpanParameter(Tag.Name, Tag.Name, TS));
469 else if (Tag.Value is DateTime TP)
470 Result.AddLast(new DateTimeParameter(Tag.Name, Tag.Name, TP));
471 else if (Tag.Value is Uri Uri)
472 Result.AddLast(new StringParameter(Tag.Name, Tag.Name, Uri.ToString()));
473 }
474 }
475
476 return Result;
477 }
478
483 public Task ReportSensorData(SensorData.Field Field)
484 {
485 return this.ReportSensorData(new SensorData.Field[] { Field });
486 }
487
492 public async Task ReportSensorData(params SensorData.Field[] Fields)
493 {
494 if (scheduler is null && Types.TryGetModuleParameter("Scheduler", out Scheduler Scheduler))
495 scheduler = Scheduler;
496
497 SensorData.Field[] ToReport = null;
498
499 lock (this.fields)
500 {
501 foreach (SensorData.Field Field in Fields)
502 {
503 this.fields[Field.Name] = Field;
504
505 if (Field.Type.HasFlag(SensorData.FieldType.Momentary))
506 {
507 this.toReport ??= new List<SensorData.Field>();
508 this.toReport.Add(Field);
509 this.hasReport = true;
510 }
511 }
512
513 if (this.hasReport)
514 {
515 if (scheduler is null)
516 {
517 ToReport = this.toReport.ToArray();
518 this.toReport.Clear();
519 this.hasReport = false;
520 }
521 else
522 {
523 if (this.nextReport != DateTime.MinValue)
524 scheduler.Remove(this.nextReport);
525
526 this.nextReport = scheduler.Add(DateTime.Now.AddMilliseconds(250), this.DoReport, null);
527 }
528 }
529 }
530
531 if (!(ToReport is null))
532 await this.NewMomentaryValues(ToReport);
533 }
534
535 private Task DoReport(object _)
536 {
537 SensorData.Field[] ToReport;
538
539 lock (this.fields)
540 {
541 ToReport = this.toReport.ToArray();
542 this.toReport.Clear();
543 this.hasReport = false;
544 }
545
546 return this.NewMomentaryValues(ToReport);
547 }
548
553 public Task StartReadout(ISensorReadout Request)
554 {
555 return this.StartReadout(Request, true);
556 }
557
561 public override bool IsReadable
562 {
563 get
564 {
565 if (this.Disabled)
566 return false;
567
568 lock (this.fields)
569 {
570 return this.fields.Count > 0;
571 }
572 }
573 }
574
581 public virtual Task StartReadout(ISensorReadout Request, bool DoneAfter)
582 {
583 List<SensorData.Field> ToReport = new List<SensorData.Field>();
584
585 lock (this.fields)
586 {
587 foreach (SensorData.Field Field in this.fields.Values)
588 {
589 if (Request.IsIncluded(Field.Name, Field.Timestamp, Field.Type))
590 ToReport.Add(Field);
591 }
592 }
593
594 if (DoneAfter || ToReport.Count > 0)
595 Request.ReportFields(DoneAfter, ToReport.ToArray());
596
597 return Task.CompletedTask;
598 }
599
603 public override bool IsControllable
604 {
605 get
606 {
607 if (this.Disabled)
608 return false;
609
610 if (this.TryGetMetaDataValue("Callback", out object Obj) && Obj is string &&
611 this.TryGetMetaDataValue("Payload", out Obj) && Obj is string &&
612 this.TryGetMetaDataValue("FieldName", out Obj) && Obj is string &&
613 this.TryGetMetaDataValue("FieldValue", out object FieldValue))
614 {
615 return
616 FieldValue is double ||
617 FieldValue is string ||
618 FieldValue is bool ||
619 FieldValue is Enum ||
620 FieldValue is DateTime ||
621 FieldValue is TimeSpan ||
622 FieldValue is Duration ||
623 FieldValue is sbyte ||
624 FieldValue is short ||
625 FieldValue is int ||
626 FieldValue is long ||
627 FieldValue is byte ||
628 FieldValue is ushort ||
629 FieldValue is uint ||
630 FieldValue is ulong;
631 }
632 else
633 return false;
634 }
635 }
636
641 public virtual Task<ControlParameter[]> GetControlParameters()
642 {
643 List<ControlParameter> Parameters = new List<ControlParameter>();
644
645 if (this.TryGetMetaDataValue("Callback", out object Obj) && Obj is string CallbackUrl &&
646 this.TryGetMetaDataValue("Payload", out Obj) && Obj is string PayloadScript &&
647 this.TryGetMetaDataValue("FieldName", out Obj) && Obj is string FieldName &&
648 this.TryGetMetaDataValue("FieldValue", out object FieldValue))
649 {
650 if (FieldValue is double d)
651 {
652 Parameters.Add(new DoubleControlParameter(FieldName, "Control", FieldName + ":", "Value to set.",
653 _ => Task.FromResult<double?>(d),
654 async (_, Value) =>
655 {
656 d = Value;
657 await this.DoCallback(CallbackUrl, PayloadScript, d);
658 }));
659 }
660 else if (FieldValue is string s)
661 {
662 Parameters.Add(new StringControlParameter(FieldName, "Control", FieldName + ":", "Value to set.",
663 _ => Task.FromResult<string>(s),
664 async (_, Value) =>
665 {
666 s = Value;
667 await this.DoCallback(CallbackUrl, PayloadScript, s);
668 }));
669 }
670 else if (FieldValue is bool b)
671 {
672 Parameters.Add(new BooleanControlParameter(FieldName, "Control", FieldName + ":", "Value to set.",
673 _ => Task.FromResult<bool?>(b),
674 async (_, Value) =>
675 {
676 b = Value;
677 await this.DoCallback(CallbackUrl, PayloadScript, b);
678 }));
679 }
680 else if (FieldValue is Enum e)
681 {
682 Parameters.Add(new EnumControlParameter(FieldName, "Control", FieldName + ":", "Value to set.", e.GetType(),
683 _ => Task.FromResult<Enum>(e),
684 async (_, Value) =>
685 {
686 e = Value;
687 await this.DoCallback(CallbackUrl, PayloadScript, e);
688 }));
689 }
690 else if (FieldValue is DateTime DT)
691 {
692 Parameters.Add(new DateTimeControlParameter(FieldName, "Control", FieldName + ":", "Value to set.", null, null,
693 _ => Task.FromResult<DateTime?>(DT),
694 async (_, Value) =>
695 {
696 DT = Value;
697 await this.DoCallback(CallbackUrl, PayloadScript, DT);
698 }));
699 }
700 else if (FieldValue is TimeSpan TS)
701 {
702 Parameters.Add(new TimeControlParameter(FieldName, "Control", FieldName + ":", "Value to set.",
703 _ => Task.FromResult<TimeSpan?>(TS),
704 async (_, Value) =>
705 {
706 TS = Value;
707 await this.DoCallback(CallbackUrl, PayloadScript, TS);
708 }));
709 }
710 else if (FieldValue is Duration D)
711 {
712 Parameters.Add(new DurationControlParameter(FieldName, "Control", FieldName + ":", "Value to set.",
713 _ => Task.FromResult<Duration>(D),
714 async (_, Value) =>
715 {
716 D = Value;
717 await this.DoCallback(CallbackUrl, PayloadScript, D);
718 }));
719 }
720 else if (FieldValue is sbyte i8)
721 {
722 Parameters.Add(new Int32ControlParameter(FieldName, "Control", FieldName + ":", "Value to set.", sbyte.MinValue, sbyte.MaxValue,
723 _ => Task.FromResult<int?>(i8),
724 async (_, Value) =>
725 {
726 i8 = (sbyte)Value;
727 await this.DoCallback<int>(CallbackUrl, PayloadScript, i8);
728 }));
729 }
730 else if (FieldValue is short i16)
731 {
732 Parameters.Add(new Int32ControlParameter(FieldName, "Control", FieldName + ":", "Value to set.", short.MinValue, short.MaxValue,
733 _ => Task.FromResult<int?>(i16),
734 async (_, Value) =>
735 {
736 i16 = (short)Value;
737 await this.DoCallback<int>(CallbackUrl, PayloadScript, i16);
738 }));
739 }
740 else if (FieldValue is int i32)
741 {
742 Parameters.Add(new Int32ControlParameter(FieldName, "Control", FieldName + ":", "Value to set.", null, null,
743 _ => Task.FromResult<int?>(i32),
744 async (_, Value) =>
745 {
746 i32 = Value;
747 await this.DoCallback<int>(CallbackUrl, PayloadScript, i32);
748 }));
749 }
750 else if (FieldValue is long i64)
751 {
752 Parameters.Add(new Int64ControlParameter(FieldName, "Control", FieldName + ":", "Value to set.", null, null,
753 _ => Task.FromResult<long?>(i64),
754 async (_, Value) =>
755 {
756 i64 = Value;
757 await this.DoCallback<long>(CallbackUrl, PayloadScript, i64);
758 }));
759 }
760 else if (FieldValue is byte ui8)
761 {
762 Parameters.Add(new Int32ControlParameter(FieldName, "Control", FieldName + ":", "Value to set.", byte.MinValue, byte.MaxValue,
763 _ => Task.FromResult<int?>(ui8),
764 async (_, Value) =>
765 {
766 ui8 = (byte)Value;
767 await this.DoCallback<int>(CallbackUrl, PayloadScript, ui8);
768 }));
769 }
770 else if (FieldValue is ushort ui16)
771 {
772 Parameters.Add(new Int32ControlParameter(FieldName, "Control", FieldName + ":", "Value to set.", ushort.MinValue, ushort.MaxValue,
773 _ => Task.FromResult<int?>(ui16),
774 async (_, Value) =>
775 {
776 ui16 = (ushort)Value;
777 await this.DoCallback<int>(CallbackUrl, PayloadScript, ui16);
778 }));
779 }
780 else if (FieldValue is uint ui32)
781 {
782 Parameters.Add(new Int64ControlParameter(FieldName, "Control", FieldName + ":", "Value to set.", uint.MinValue, uint.MaxValue,
783 _ => Task.FromResult<long?>(ui32),
784 async (_, Value) =>
785 {
786 ui32 = (uint)Value;
787 await this.DoCallback<long>(CallbackUrl, PayloadScript, ui32);
788 }));
789 }
790 else if (FieldValue is ulong ui64)
791 {
792 Parameters.Add(new DoubleControlParameter(FieldName, "Control", FieldName + ":", "Value to set.", ulong.MinValue, ulong.MaxValue,
793 _ => Task.FromResult<double?>(ui64),
794 async (_, Value) =>
795 {
796 ui64 = (ulong)Value;
797 await this.DoCallback<double>(CallbackUrl, PayloadScript, ui64);
798 }));
799 }
800 }
801
802 return Task.FromResult(Parameters.ToArray());
803 }
804
805 private async Task DoCallback<T>(string CallbackUrl, string PayloadScript, T Value)
806 {
807 Variables v = new Variables
808 {
809 { "Value", Value }
810 };
811
812 object Payload = await Expression.EvalAsync(PayloadScript, v);
813 ContentResponse Content = await InternetContent.PostAsync(new Uri(CallbackUrl), Payload);
814 Content.AssertOk();
815 }
816
820 public override Task<IEnumerable<ICommand>> Commands => this.GetCommands();
821
822 private async Task<IEnumerable<ICommand>> GetCommands()
823 {
824 List<ICommand> Commands = new List<ICommand>();
825 Commands.AddRange(await base.Commands);
826
827 Commands.Add(new AddMetaDataString(this));
828 Commands.Add(new AddMetaDataInt32(this));
829 Commands.Add(new AddMetaDataInt64(this));
830 Commands.Add(new AddMetaDataDouble(this));
831 Commands.Add(new AddMetaDataBoolean(this));
832 Commands.Add(new AddMetaDataDateTime(this));
833 Commands.Add(new AddMetaDataTimeSpan(this));
834 Commands.Add(new AddMetaDataDuration(this));
835
836 return Commands.ToArray();
837 }
838
839 }
840}
Helps with parsing of commong data types.
Definition: CommonTypes.cs:15
static bool TryParse(string s, out double Value)
Tries to decode a string encoded double.
Definition: CommonTypes.cs:48
Contains information about a response to a content request.
void AssertOk()
Asserts response is OK.
Static class managing encoding and decoding of internet content.
static Task< ContentResponse > PostAsync(Uri Uri, object Data, params KeyValuePair< string, string >[] Headers)
Posts to a resource, using a Uniform Resource Identifier (or Locator).
Helps with common XML-related tasks.
Definition: XML.cs:21
static bool TryParse(string s, out DateTime Value)
Tries to decode a string encoded DateTime.
Definition: XML.cs:892
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
static Exception UnnestException(Exception Exception)
Unnests an exception, to extract the relevant inner exception.
Definition: Log.cs:828
Base class for form fields
Definition: Field.cs:17
string Var
Variable name
Definition: Field.cs:82
string ValueString
Value as a single string. If field contains multiple values, they will be concatenated into a single ...
Definition: Field.cs:102
string[] ValueStrings
Values for the field (string representations).
Definition: Field.cs:97
Field(DataForm Form, string Var, string Label, bool Required, string[] ValueStrings, KeyValuePair< string, string >[] Options, string Description, DataType DataType, ValidationMethod ValidationMethod, string Error, bool PostBack, bool ReadOnly, bool NotSame)
Base class for form fields
Definition: Field.cs:52
Current state of a property form being built.
Dictionary< string, Page > PageByLabel
Pages by page label.
Class managing a page in a data form layout.
Definition: Page.cs:11
Static class that dynamically manages types and interfaces available in the runtime environment.
Definition: Types.cs:15
static bool TryGetModuleParameter(string Name, out object Value)
Tries to get a module parameter value.
Definition: Types.cs:607
Contains information about a language.
Definition: Language.cs:17
Task< string > GetStringAsync(Type Type, int Id, string Default)
Gets the string value of a string ID. If no such string exists, a string is created with the default ...
Definition: Language.cs:209
async Task< Namespace > GetNamespaceAsync(string Name)
Gets the namespace object, given its name, if available.
Definition: Language.cs:99
Contains information about a namespace in a language.
Definition: Namespace.cs:17
Task< LanguageString > GetStringAsync(int Id)
Gets the string object, given its ID, if available.
Definition: Namespace.cs:65
Basic access point for runtime language localization.
Definition: Translator.cs:16
static async Task< Language > GetLanguageAsync(string Code)
Gets the languge object, given its language code, if available.
Definition: Translator.cs:42
Class that can be used to schedule events in time. It uses a timer to execute tasks at the appointed ...
Definition: Scheduler.cs:14
bool Remove(DateTime When)
Removes an event scheduled for a given point in time.
Definition: Scheduler.cs:186
DateTime Add(DateTime When, Action< object > Callback, object State)
Adds an event.
Definition: Scheduler.cs:54
Class managing a script expression.
Definition: Expression.cs:41
static Task< object > EvalAsync(string Script)
Evaluates script, in string format.
Definition: Expression.cs:5946
Collection of variables.
Definition: Variables.cs:25
string Name
If the node is provisioned is not. Property is editable.
Task NewMomentaryValues(params Field[] Values)
Reports newly measured values.
Class for the root node of the Metering topology.
Definition: Root.cs:10
Base class for all provisioned metering nodes.
Tokens available in request.
Definition: RequestOrigin.cs:9
Class representing a meta-data value.
Virtual node, that can be used as a placeholder for services.
Definition: VirtualNode.cs:28
object GetMetaData(string Name)
Gets a meta-data value, if available.
Definition: VirtualNode.cs:398
virtual Task StartReadout(ISensorReadout Request, bool DoneAfter)
Starts the readout of the sensor.
Definition: VirtualNode.cs:581
override async Task< IEnumerable< Parameter > > GetDisplayableParametersAsync(Language Language, RequestOrigin Caller)
Gets displayable parameters.
Definition: VirtualNode.cs:443
override async Task AnnotatePropertyForm(FormState Form)
Annotates the property form.
Definition: VirtualNode.cs:86
VirtualNode()
Virtual node, that can be used as a placeholder for services.
Definition: VirtualNode.cs:39
async Task ReportSensorData(params SensorData.Field[] Fields)
Reports sensor data on the node.
Definition: VirtualNode.cs:492
Task StartReadout(ISensorReadout Request)
Starts the readout of the sensor.
Definition: VirtualNode.cs:553
virtual Task< ControlParameter[]> GetControlParameters()
Get control parameters for the actuator.
Definition: VirtualNode.cs:641
override Task< bool > AcceptsParentAsync(INode Parent)
If the node accepts a presumptive parent, i.e. can be added to that parent (if that parent accepts th...
Definition: VirtualNode.cs:74
override bool IsControllable
If the node can be controlled.
Definition: VirtualNode.cs:604
override Task< string > GetTypeNameAsync(Language Language)
Gets the type name of the node.
Definition: VirtualNode.cs:54
override bool IsReadable
If the node can be read.
Definition: VirtualNode.cs:562
override Task< IEnumerable< ICommand > > Commands
Available command objects. If no commands are available, null is returned.
Definition: VirtualNode.cs:820
Task ValidateCustomProperty(Field Field)
Performs custom validation of a property.
Definition: VirtualNode.cs:234
MetaDataValue[] MetaData
Meta-data attached to virtual node.
Definition: VirtualNode.cs:47
Task SetCustomProperty(Field Field)
Sets the custom parameter to the value(s) provided in the field.
Definition: VirtualNode.cs:315
bool TryGetMetaDataValue(string Name, out object Value)
Tries to get a meta-data value
Definition: VirtualNode.cs:198
Task ReportSensorData(SensorData.Field Field)
Reports sensor data on the node.
Definition: VirtualNode.cs:483
async Task SetMetaData(string Name, object Value)
Sets a meta-data value.
Definition: VirtualNode.cs:411
override async Task< bool > AcceptsChildAsync(INode Child)
If the node accepts a presumptive child, i.e. can receive as a child (if that child accepts the node ...
Definition: VirtualNode.cs:64
Interface for objects that want to handle custom properties in property forms.
Interface for actuator nodes.
Definition: IActuator.cs:10
Interface for nodes that are published through the concentrator interface.
Definition: INode.cs:49
Task UpdateAsync()
Updates the node (in persisted storage).
INode Parent
Parent Node, or null if a root node.
Definition: INode.cs:116
Task< bool > AcceptsParentAsync(INode Parent)
If the node accepts a presumptive parent, i.e. can be added to that parent (if that parent accepts th...
Interface for sensor nodes.
Definition: ISensor.cs:9
Interface for classes managing sensor data readouts.
bool IsIncluded(string FieldName)
Checks if a field with the given parameters is included in the readout.
Task ReportFields(bool Done, params Field[] Fields)
Report read fields to the client.
Definition: ImplTypes.g.cs:58
Represents a duration value, as defined by the xsd:duration data type: http://www....
Definition: Duration.cs:14