11bb5b742e
- move progetti core di MTC in net8 a scratch (da rivedere...)
601 lines
18 KiB
C#
601 lines
18 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using IOB_UT_NEXT;
|
|
using MTConnect;
|
|
using MTConnect.Assets;
|
|
using MTConnect.Clients;
|
|
using MTConnect.Devices;
|
|
using MTConnect.Observations;
|
|
using MTConnect.Streams;
|
|
using NLog;
|
|
using Spectre.Console;
|
|
|
|
namespace IOB_WIN_MTC_CLI
|
|
{
|
|
public class IobComm
|
|
{
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// Init classe
|
|
/// </summary>
|
|
public IobComm()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Init Classe
|
|
/// </summary>
|
|
/// <param name="opcAddr"></param>
|
|
public IobComm(string opcAddr)
|
|
{
|
|
baseUrl = opcAddr;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Init Classe
|
|
/// </summary>
|
|
/// <param name="opcAddr"></param>
|
|
/// <param name="titolo"></param>
|
|
/// <param name="sottotitolo"></param>
|
|
public IobComm(string opcAddr, string titolo, string sottotitolo)
|
|
{
|
|
baseUrl = opcAddr;
|
|
title = titolo;
|
|
subtitle = sottotitolo;
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Methods
|
|
|
|
public void DoConfig()
|
|
{
|
|
msgData = new List<string>();
|
|
dispData = new Dictionary<string, double>();
|
|
|
|
// primo display
|
|
msgData.Add("Starting CLI setup...");
|
|
DoDisplayAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esecuzione log secondo conf
|
|
/// </summary>
|
|
/// <param name="msg"></param>
|
|
public void doLog(string msg = "")
|
|
{
|
|
try
|
|
{
|
|
if (fileLog)
|
|
{
|
|
lg.Info($"{msg}");
|
|
}
|
|
|
|
if (consoleLog)
|
|
{
|
|
Console.WriteLine(msg);
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Console.WriteLine($"Eccezione in log:{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esecuzione probe call indipendente
|
|
/// </summary>
|
|
public void ForceProbe()
|
|
{
|
|
// init
|
|
sw.Restart();
|
|
msgData = new List<string>();
|
|
dispData = new Dictionary<string, double>();
|
|
|
|
// primo display
|
|
msgData.Add("Calling PROBE...");
|
|
DoDisplayAsync();
|
|
|
|
// inizio processing
|
|
var prbClient = new MTConnectHttpProbeClient(baseUrl);
|
|
prbClient.Timeout = 20000;
|
|
var prbDoc = prbClient.Get();
|
|
// preparo output
|
|
if (prbDoc == null)
|
|
{
|
|
msgData.Add($"Preliminari Probe | {sw.ElapsedMilliseconds}ms | No answer, continue...");
|
|
}
|
|
else
|
|
{
|
|
displayProbeDoc("Preliminari Probe RECEIVED", prbDoc);
|
|
}
|
|
}
|
|
|
|
public void MainLoop()
|
|
{
|
|
sw.Restart();
|
|
msgData = new List<string>();
|
|
dispData = new Dictionary<string, double>();
|
|
|
|
ConsoleKeyInfo answ = Console.ReadKey();
|
|
while (answ.Key != ConsoleKey.Escape)
|
|
{
|
|
msgData.Add($"CONSOLE LOG: {consoleLog}");
|
|
msgData.Add($"FILE LOG: {fileLog}");
|
|
DoDisplayAsync();
|
|
|
|
answ = Console.ReadKey();
|
|
// controllo key...
|
|
if (answ.Key == ConsoleKey.C)
|
|
{
|
|
consoleLog = !consoleLog;
|
|
}
|
|
else if (answ.Key == ConsoleKey.F)
|
|
{
|
|
fileLog = !fileLog;
|
|
}
|
|
else if (answ.Key == ConsoleKey.P)
|
|
{
|
|
msgData = new List<string>();
|
|
dispData = new Dictionary<string, double>();
|
|
ForceProbe();
|
|
}
|
|
else if (answ.Key == ConsoleKey.R)
|
|
{
|
|
msgData = new List<string>();
|
|
dispData = new Dictionary<string, double>();
|
|
client.Stop();
|
|
Task.Delay(500);
|
|
dtStart = DateTime.Now;
|
|
StartClient();
|
|
msgData.Add($"Client restarted!");
|
|
}
|
|
else if (answ.Key == ConsoleKey.S)
|
|
{
|
|
msgData = new List<string>();
|
|
dispData = new Dictionary<string, double>();
|
|
client.Stop();
|
|
msgData.Add($"Client stopped!");
|
|
}
|
|
}
|
|
doLog("...closing Now!");
|
|
}
|
|
|
|
private DateTime displayVeto = DateTime.Now;
|
|
|
|
/// <summary>
|
|
/// Avvio del thread principale
|
|
/// </summary>
|
|
public void StartClient()
|
|
{
|
|
// init
|
|
sw.Restart();
|
|
msgData = new List<string>();
|
|
dispData = new Dictionary<string, double>();
|
|
|
|
// primo display
|
|
msgData.Add("Client App setup...");
|
|
DoDisplayAsync();
|
|
|
|
// setup client
|
|
client = new MTConnectHttpClient(baseUrl);
|
|
// sample interval
|
|
client.Interval = 500;
|
|
// timeout x richieste
|
|
client.Timeout = 4000;
|
|
// timeout riconnessione
|
|
client.ReconnectionInterval = 5000;
|
|
|
|
// aggancio eventi
|
|
if (enabAsset)
|
|
{
|
|
client.AssetsReceived += Client_AssetsReceived;
|
|
}
|
|
client.ClientStarted += Client_ClientStarted;
|
|
client.ClientStopped += Client_ClientStopped;
|
|
client.ConnectionError += Client_ConnectionError;
|
|
client.CurrentReceived += Client_CurrentReceived;
|
|
client.ProbeReceived += Client_ProbeReceived;
|
|
if (enabSample)
|
|
{
|
|
client.SampleReceived += Client_SampleReceived;
|
|
}
|
|
if (enabObserv)
|
|
{
|
|
// conviene usare sample x avere la stessa cosa ma con altre info...
|
|
client.ObservationReceived += Client_ObservationReceived;
|
|
}
|
|
|
|
msgData.Add($"Setup completed! | {sw.ElapsedMilliseconds}ms");
|
|
DoDisplayAsync();
|
|
|
|
// vero avvio
|
|
client.Start();
|
|
msgData.Add($"Client Started | {sw.ElapsedMilliseconds} ms");
|
|
DoDisplayAsync();
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Protected Fields
|
|
|
|
protected bool enabAsset = true;
|
|
protected bool enabObserv = false;
|
|
protected bool enabSample = true;
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Protected Properties
|
|
|
|
protected bool consoleLog { get; set; } = false;
|
|
|
|
protected bool fileLog { get; set; } = true;
|
|
|
|
#endregion Protected Properties
|
|
|
|
#region Protected Methods
|
|
|
|
/// <summary>
|
|
/// Main display function
|
|
/// </summary>
|
|
/// <param name="msgList"></param>
|
|
/// <param name="graphData"></param>
|
|
protected async Task DoDisplayAsync()
|
|
{
|
|
// attesa che non sia in corso update
|
|
while (inRefresh || displayVeto > DateTime.Now)
|
|
{
|
|
//Thread.Sleep(rand.Next(50, 150));
|
|
await Task.Delay(rand.Next(50, 150));
|
|
}
|
|
|
|
try
|
|
{
|
|
inRefresh = true;
|
|
displayVeto = DateTime.Now.AddMilliseconds(1000);
|
|
AnsiConsole.Clear();
|
|
|
|
// titolo
|
|
AnsiConsole.Write(
|
|
new FigletText(title)
|
|
.LeftJustified()
|
|
.Color(Color.Cyan1));
|
|
|
|
var rule = new Rule(subtitle);
|
|
rule.RightJustified();
|
|
AnsiConsole.Write(rule);
|
|
|
|
// se presenti messaggi
|
|
if (msgData.Count > 0)
|
|
{
|
|
foreach (var msg in msgData)
|
|
{
|
|
if (fileLog)
|
|
{
|
|
lg.Info(msg);
|
|
}
|
|
AnsiConsole.MarkupLine(msg);
|
|
}
|
|
rule = new Rule();
|
|
rule.RuleStyle("grey dim");
|
|
AnsiConsole.Write(rule);
|
|
}
|
|
|
|
// se presenti graph...
|
|
if (dispData.Count > 0)
|
|
{
|
|
foreach (var graph in dispData)
|
|
{
|
|
}
|
|
rule = new Rule();
|
|
rule.RuleStyle("grey dim");
|
|
AnsiConsole.Write(rule);
|
|
}
|
|
|
|
// comandi
|
|
if (commandList.Count > 0)
|
|
{
|
|
// mostro cmd list...
|
|
foreach (var cmd in commandList)
|
|
{
|
|
AnsiConsole.MarkupLine(cmd);
|
|
}
|
|
|
|
rule = new Rule();
|
|
rule.RuleStyle("grey dim");
|
|
AnsiConsole.Write(rule);
|
|
}
|
|
string uptime = $"Uptime: {DateTime.Now.Subtract(dtStart).TotalMinutes:N1} min";
|
|
AnsiConsole.WriteLine(uptime);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Console.WriteLine($"Eccezione in DoDisplay:{Environment.NewLine}{exc}");
|
|
}
|
|
inRefresh = false;
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
|
|
#region Private Fields
|
|
|
|
private DateTime dtStart = DateTime.Now;
|
|
|
|
private static Logger lg = LogManager.GetCurrentClassLogger();
|
|
|
|
private string baseUrl = "192.168.1.27:5000";
|
|
|
|
private List<string> commandList = new List<string>() {
|
|
"R = Restart Service | S = Stop Service | P = force probe",
|
|
"C = toggle console log | F = toggle file log | Press ESC to exit"
|
|
};
|
|
|
|
/// <summary>
|
|
/// Dizionario variabili conteggio collezionate
|
|
/// </summary>
|
|
private Dictionary<string, int> DataCounters = new Dictionary<string, int>();
|
|
|
|
private Dictionary<string, double> dispData = new Dictionary<string, double>();
|
|
private bool inRefresh = false;
|
|
private List<string> msgData = new List<string>();
|
|
private Random rand = new Random();
|
|
private string sep = "------------------------";
|
|
|
|
private string subtitle = "EgalWare 2024+";
|
|
|
|
private Stopwatch sw = new Stopwatch();
|
|
|
|
private string title = "MtConnect Client";
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Private Properties
|
|
|
|
private MTConnectHttpClient client { get; set; } = new MTConnectHttpClient("");
|
|
|
|
#endregion Private Properties
|
|
|
|
#region Private Methods
|
|
|
|
private void Client_AssetsReceived(object sender, MTConnect.Assets.IAssetsResponseDocument document)
|
|
{
|
|
displayAsset(document);
|
|
}
|
|
|
|
private void Client_ClientStarted(object sender, EventArgs e)
|
|
{
|
|
msgData = new List<string>();
|
|
msgData.Add($"Client Started!");
|
|
msgData.Add(sep);
|
|
DoDisplayAsync();
|
|
}
|
|
|
|
private void Client_ClientStopped(object sender, EventArgs e)
|
|
{
|
|
msgData = new List<string>();
|
|
msgData.Add($"Client Stopped!");
|
|
msgData.Add(sep);
|
|
DoDisplayAsync();
|
|
}
|
|
|
|
private void Client_ConnectionError(object sender, Exception exc)
|
|
{
|
|
msgData = new List<string>();
|
|
msgData.Add($"Connection ERROR returned!");
|
|
msgData.Add($"{exc}");
|
|
msgData.Add(sep);
|
|
DoDisplayAsync();
|
|
}
|
|
|
|
private void Client_CurrentReceived(object sender, MTConnect.Streams.IStreamsResponseDocument document)
|
|
{
|
|
displayCurrent(document);
|
|
}
|
|
|
|
private void Client_ObservationReceived(object sender, IObservation observ)
|
|
{
|
|
msgData = new List<string>();
|
|
msgData.Add("OBSERVATION");
|
|
msgData.Add(sep);
|
|
processObservation(observ);
|
|
}
|
|
|
|
private void Client_ProbeReceived(object sender, MTConnect.Devices.IDevicesResponseDocument document)
|
|
{
|
|
displayProbeDoc("Client Probe RECEIVED", document);
|
|
}
|
|
|
|
private void Client_SampleReceived(object sender, MTConnect.Streams.IStreamsResponseDocument document)
|
|
{
|
|
displaySample(document);
|
|
}
|
|
|
|
private void displayAsset(IAssetsResponseDocument document)
|
|
{
|
|
msgData = new List<string>();
|
|
int numAssets = 0;
|
|
msgData.Add("ASSET received");
|
|
doLog(sep);
|
|
foreach (var asset in document.Assets)
|
|
{
|
|
// Print AssetId to the Console
|
|
doLog($"Asset: {asset.AssetId}");
|
|
numAssets++;
|
|
}
|
|
msgData.Add($" Found [green]{numAssets} Assets[/]");
|
|
|
|
DoDisplayAsync();
|
|
}
|
|
|
|
private void displayCurrent(IStreamsResponseDocument document)
|
|
{
|
|
msgData = new List<string>();
|
|
int numStream = 0;
|
|
int numCompo = 0;
|
|
msgData.Add($"CURRENT received!");
|
|
|
|
foreach (var deviceStream in document.Streams)
|
|
{
|
|
// DeviceStream
|
|
msgData.Add($" Stream: {deviceStream.Name}");
|
|
numStream++;
|
|
|
|
// Component Streams
|
|
foreach (var componentStream in deviceStream.ComponentStreams)
|
|
{
|
|
processData(componentStream);
|
|
numCompo++;
|
|
}
|
|
}
|
|
msgData.Add($" Found [green]{numStream} Streams[/]");
|
|
msgData.Add($" Found [yellow]{numCompo} Components[/]");
|
|
|
|
DoDisplayAsync();
|
|
}
|
|
|
|
private void displayProbeDoc(string message, IDevicesResponseDocument prbDoc)
|
|
{
|
|
msgData = new List<string>();
|
|
msgData.Add(message);
|
|
msgData.Add(sep);
|
|
|
|
foreach (var device in prbDoc.Devices)
|
|
{
|
|
// Device
|
|
msgData.Add($"DEV: {device.Id}");
|
|
int numDataItem = 0;
|
|
int numComponents = 0;
|
|
int numCompositions = 0;
|
|
|
|
// All DataItems (traverse the entire Device model)
|
|
if (device.DataItems.Count() > 0)
|
|
{
|
|
foreach (var dataItem in device.GetDataItems())
|
|
{
|
|
lg.Trace($" DItm | {dataItem.IdPath}");
|
|
numDataItem++;
|
|
}
|
|
}
|
|
msgData.Add($" Found [green]{numDataItem} DataItems[/]");
|
|
|
|
// All Components (traverse the entire Device model)
|
|
if (device.Components.Count() > 0)
|
|
{
|
|
foreach (var component in device.GetComponents())
|
|
{
|
|
lg.Trace($" Comp | {component.IdPath}");
|
|
numComponents++;
|
|
}
|
|
}
|
|
msgData.Add($" Found [blue]{numComponents} Components[/]");
|
|
|
|
// All Compositions (traverse the entire Device model)
|
|
if (device.Compositions.Count() > 0)
|
|
{
|
|
foreach (var composition in device.GetCompositions())
|
|
{
|
|
lg.Trace($" Cpst | {composition.IdPath}");
|
|
numCompositions++;
|
|
}
|
|
}
|
|
msgData.Add($" Found [yellow]{numCompositions} Compositions[/]");
|
|
}
|
|
msgData.Add(sep);
|
|
|
|
DoDisplayAsync();
|
|
}
|
|
|
|
private void displaySample(IStreamsResponseDocument document)
|
|
{
|
|
msgData = new List<string>();
|
|
int numStream = 0;
|
|
int numCompo = 0;
|
|
msgData.Add($"SAMPLE");
|
|
|
|
foreach (var deviceStream in document.Streams)
|
|
{
|
|
// DeviceStream
|
|
msgData.Add($" Stream: {deviceStream.Name}");
|
|
numStream++;
|
|
|
|
// Component Streams
|
|
foreach (var componentStream in deviceStream.ComponentStreams)
|
|
{
|
|
processData(componentStream);
|
|
numCompo++;
|
|
}
|
|
}
|
|
msgData.Add($" Found [green]{numStream} Streams[/]");
|
|
msgData.Add($" Found [yellow]{numCompo} Components[/]");
|
|
|
|
DoDisplayAsync();
|
|
}
|
|
|
|
private void processData(IComponentStream dataStream)
|
|
{
|
|
int numCondition = 0;
|
|
int numEvent = 0;
|
|
int numSample = 0;
|
|
// DataItems (Samples, Events, and Conditions)
|
|
foreach (var observation in dataStream.Observations)
|
|
{
|
|
processObservation(observation);
|
|
switch (observation.Category)
|
|
{
|
|
case DataItemCategory.CONDITION:
|
|
numCondition++;
|
|
break;
|
|
|
|
case DataItemCategory.EVENT:
|
|
numEvent++;
|
|
break;
|
|
|
|
case DataItemCategory.SAMPLE:
|
|
numSample++;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
msgData.Add($" Component {dataStream.Name} | {numCondition} Conditions | {numEvent} Events | {numSample} Samples");
|
|
}
|
|
|
|
private void processObservation(IObservation observation)
|
|
{
|
|
string sMsg = $" - {observation.DataItemId} | {observation.Category}";
|
|
#if false
|
|
switch (observation.Category)
|
|
{
|
|
case MTConnect.Devices.DataItemCategory.CONDITION:
|
|
break;
|
|
|
|
case MTConnect.Devices.DataItemCategory.EVENT:
|
|
break;
|
|
|
|
case MTConnect.Devices.DataItemCategory.SAMPLE:
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
#endif
|
|
if (observation.Values != null && observation.Values.Count() > 0)
|
|
{
|
|
foreach (var item in observation.Values)
|
|
{
|
|
sMsg += $" | {item.Key}: {item.Value}";
|
|
}
|
|
}
|
|
doLog(sMsg);
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |