MonitorCommand.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. using System.Globalization;
  2. using System.Runtime.InteropServices.JavaScript;
  3. using System.Text;
  4. using System.Text.Json;
  5. using Quadarax.Foundation.Core.Data;
  6. using Quadarax.Foundation.Core.QConsole;
  7. using Quadarax.Foundation.Core.QConsole.Argument;
  8. using Quadarax.Foundation.Core.QConsole.Attributes;
  9. using Quadarax.Foundation.Core.QConsole.Value;
  10. using Quadarax.Foundation.Core.QMonitor.Interfaces;
  11. using Quadarax.Foundation.Core.Value.Extensions;
  12. using Result = Quadarax.Foundation.Core.Value.Result;
  13. namespace Quadarax.Foundation.Core.QMonitor.Console.Commands
  14. {
  15. [CommandDefinition]
  16. internal class MonitorCommand : BaseCommand
  17. {
  18. #region *** Constants ***
  19. private const string CS_CMD_MONITOR_NAME = "monitor";
  20. private const string CS_CMD_MONITOR_DESC = "Monitor specific single channel";
  21. protected const string CS_ARG_NAME_IID = "iid";
  22. private const string CS_ARG_HINT_IID = "<instance_identifier>";
  23. private const string CS_ARG_DESC_IID = "Specify instance identifier to listen from.";
  24. protected const string CS_ARG_NAME_CHANNEL = "channel";
  25. private const string CS_ARG_HINT_CHANNEL = "<chennel>";
  26. private const string CS_ARG_DESC_CHANNEL = "Specify full channel name to monitor.";
  27. protected const string CS_ARG_NAME_REFRESH = "refresh";
  28. private const string CS_ARG_HINT_REFRESH = "<refresh_interval>";
  29. private const string CS_ARG_DESC_REFRESH = "Specify receiver refresh interval to detect changes. Default is 00:00:05.";
  30. protected const string CS_ARG_NAME_GENFILE = "genfile";
  31. private const string CS_ARG_HINT_GENFILE = "<general_file>";
  32. private const string CS_ARG_DESC_GENFILE = "Use general metadata from json file during initialization (no needs to wait to receive).";
  33. #endregion
  34. #region *** Properties ***
  35. public override string Name => CS_CMD_MONITOR_NAME;
  36. public override string Description => CS_CMD_MONITOR_DESC;
  37. private string InstanceIdentifier { get; set; }
  38. private string ChannelName { get; set; }
  39. private TimeSpan RefreshInterval { get; set; }
  40. private string GeneralFile { get; set; }
  41. #endregion
  42. #region *** Private fields ***
  43. private long _dumpCnt;
  44. private MonData? _lastData;
  45. private IDictionary<string, MonData> _lastDataCollection = new Dictionary<string, MonData>();
  46. #endregion
  47. #region *** Constructor ***
  48. public MonitorCommand(Engine engine) : base(engine)
  49. {
  50. }
  51. #endregion
  52. #region *** Execute ***
  53. protected override Result OnExecute()
  54. {
  55. WriteInfo($"Refresh interval is set to {RefreshInterval}");
  56. WriteInfo($"Waiting for channel definition '{InstanceIdentifier}' and channel '{ChannelName}'...");
  57. using (var hnd = Receiver.CreateHandler(InstanceIdentifier, ChannelName, RefreshInterval,GeneralFile, true))
  58. {
  59. hnd.ReceiverHandlerStateChanged += OnReceiverHandlerStateChanged;
  60. hnd.ReceiverHandlerDataChanged += OnReceiverHandlerDataChanged;
  61. hnd.Play(false);
  62. WriteCaption("To close receiver press any key ...");
  63. System.Console.ReadKey();
  64. }
  65. return new Result();
  66. }
  67. #endregion
  68. #region *** Private Operations ***
  69. protected override void OnInitialize()
  70. {
  71. base.OnInitialize();
  72. InstanceIdentifier = GetArgumentValueOrDefault<string>(CS_ARG_NAME_IID);
  73. ChannelName = GetArgumentValueOrDefault<string>(CS_ARG_NAME_CHANNEL);
  74. RefreshInterval = GetArgumentValueOrDefault<TimeSpan>(CS_ARG_NAME_REFRESH);
  75. GeneralFile = GetArgumentValueOrDefault<string>(CS_ARG_NAME_GENFILE);
  76. }
  77. protected override IEnumerable<AbstractArgument> OnSetupArguments()
  78. {
  79. var list = base.OnSetupArguments().ToList();
  80. list.Add(new NamedArgument(CS_ARG_NAME_IID, CS_ARG_HINT_IID, CS_ARG_DESC_IID, TypeValuesEnum.String,string.Empty,true));
  81. list.Add(new NamedArgument(CS_ARG_NAME_CHANNEL, CS_ARG_HINT_CHANNEL, CS_ARG_DESC_CHANNEL, TypeValuesEnum.String,string.Empty,true));
  82. list.Add(new NamedArgument(CS_ARG_NAME_REFRESH, CS_ARG_HINT_REFRESH, CS_ARG_DESC_REFRESH, TypeValuesEnum.TimeSpan,TimeSpan.FromSeconds(5).ToString(),false));
  83. list.Add(new NamedArgument(CS_ARG_NAME_GENFILE, CS_ARG_HINT_GENFILE, CS_ARG_DESC_GENFILE, TypeValuesEnum.String, string.Empty, false));
  84. return list;
  85. }
  86. private void OnReceiverHandlerDataChanged(IReceiverHandler sender, MonData newData)
  87. {
  88. RenderData(sender.Descriptor, newData);
  89. }
  90. private void OnReceiverHandlerStateChanged(IReceiverHandler sender, ReceiverHandlerStateEnum state)
  91. {
  92. WriteInfo($"! Receiver state change to {sender.State.ToString().ToUpper()}");
  93. }
  94. private void RenderData(MonItemGeneral descriptor, MonData data)
  95. {
  96. var firstLine = $"*** Dump [{_dumpCnt}] {descriptor.ViewType} * {descriptor.Caption} ***";
  97. WriteInfo(firstLine);
  98. WriteCaption($"Timestamp: {data.Timestamp} Name: {data.Name}");
  99. WriteInfo(new('-', firstLine.Length));
  100. var diff = _lastData?.Diff(data);
  101. if (descriptor.ViewType == MonItemGeneral.MonViewType.Item)
  102. {
  103. //item view
  104. foreach (var item in descriptor.Items.OrderBy(x=>x.Order))
  105. {
  106. var sb = new StringBuilder();
  107. if (diff != null)
  108. {
  109. if (diff.ContainsKey(item.Name)) sb.Append("[*] ");
  110. }
  111. sb.Append(string.IsNullOrEmpty(item.Label) ? item.Name : item.Label).Append(" : ");
  112. var properties = ParseProperties(JsonDocument.Parse(data.Data).RootElement);
  113. var arg = properties.FirstOrDefault(x => string.Equals(x.Name, item.Name, StringComparison.InvariantCultureIgnoreCase));
  114. sb.Append(arg != null ? arg.Value : "N/A");
  115. WriteInfo(sb.ToString());
  116. }
  117. }
  118. WriteInfo(new('-', firstLine.Length));
  119. _lastData = data;
  120. _dumpCnt++;
  121. }
  122. private TypedArgument[] ParseProperties(JsonElement element)
  123. {
  124. var result = new List<TypedArgument>();
  125. foreach (var property in element.EnumerateObject())
  126. {
  127. if (property.Value.ValueKind.In(JsonValueKind.False, JsonValueKind.True, JsonValueKind.Number,
  128. JsonValueKind.String))
  129. {
  130. TypedArgument? arg = null;
  131. if (property.Value.ValueKind.In(JsonValueKind.False, JsonValueKind.True))
  132. {
  133. arg = new TypedArgument(property.Name, property.Value.GetBoolean());
  134. }
  135. else if (property.Value.ValueKind == JsonValueKind.Null)
  136. {
  137. result.Add(new TypedArgument(property.Name,null, typeof(string)));
  138. }
  139. else if (property.Value.ValueKind == JsonValueKind.Number)
  140. {
  141. result.Add(new TypedArgument(property.Name, property.Value.GetDecimal()));
  142. }
  143. else if (property.Value.ValueKind == JsonValueKind.String)
  144. {
  145. result.Add(new TypedArgument(property.Name, property.Value.GetString()));
  146. }
  147. if (arg != null)
  148. result.Add(arg);
  149. }
  150. }
  151. return result.ToArray();
  152. }
  153. #endregion
  154. }
  155. }