Compare commits
5 Commits
05ada6189b
...
1ba32813bb
| Author | SHA1 | Date | |
|---|---|---|---|
| 1ba32813bb | |||
| 7a4d0d7999 | |||
| 0fdba701fa | |||
| 6f0cb1bc1c | |||
| 5ed0c3311e |
@ -2,16 +2,12 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
using Hi.Common;
|
|
||||||
using Hi.Common.FileLines;
|
using Hi.Common.FileLines;
|
||||||
using Hi.Geom;
|
using Hi.Common.Messages;
|
||||||
using Hi.HiNcKits;
|
using Hi.HiNcKits;
|
||||||
using Hi.MachiningProcs;
|
using Hi.MachiningProcs;
|
||||||
using Hi.MachiningSteps;
|
using Hi.MachiningSteps;
|
||||||
using Hi.Mech;
|
using Hi.NcParsers;
|
||||||
using Hi.Mech.Topo;
|
|
||||||
using Hi.Numerical;
|
|
||||||
|
|
||||||
namespace Sample.Common;
|
namespace Sample.Common;
|
||||||
|
|
||||||
@ -24,114 +20,40 @@ public static class DemoSessionMessage
|
|||||||
#region Demo_UseSessionMessageHost
|
#region Demo_UseSessionMessageHost
|
||||||
internal static void DemoUseSessionMessageHost(LocalProjectService localProjectService)
|
internal static void DemoUseSessionMessageHost(LocalProjectService localProjectService)
|
||||||
{
|
{
|
||||||
SessionProgress sessionMessageHost = localProjectService.SessionProgress;
|
// Session messages are partitioned by kind into three sinks on LocalProjectService:
|
||||||
|
// - ShellProgress: session-level routine / lifecycle messages
|
||||||
|
// (session-scoped: null outside BeginSession/EndSession).
|
||||||
|
// - NcDiagnosticProgress: NC-pipeline diagnostics, anchored to the NC source sentence.
|
||||||
|
// - StepDiagnosticProgress: diagnostics anchored to a motion step.
|
||||||
|
|
||||||
SessionProgress.FilterFlag filterFlags =
|
ShellProgress shellProgress = localProjectService.ShellProgress;
|
||||||
SessionProgress.FilterFlag.NC |
|
List<IMessage> shellMessages = shellProgress == null
|
||||||
SessionProgress.FilterFlag.Progress |
|
? new List<IMessage>() : shellProgress.Messages.ToList();
|
||||||
SessionProgress.FilterFlag.Error;
|
foreach (IMessage message in shellMessages)
|
||||||
string filterText = null;
|
Console.WriteLine(
|
||||||
var filteredSessionMessageList = sessionMessageHost
|
$"Shell [{message.GetSeverity()}] {message.GetId()}: {message.GetNotification()}");
|
||||||
.GetFliteredList(filterFlags, filterText);
|
|
||||||
|
|
||||||
foreach (var sessionMessage in filteredSessionMessageList)
|
foreach (NcDiagnostic diagnostic in
|
||||||
|
localProjectService.NcDiagnosticProgress.Diagnostics.ToList())
|
||||||
{
|
{
|
||||||
//M.I.: Message Index.
|
var ncLine = diagnostic.SentenceCarrier?.GetSentence()?.FirstIndexedFileLine;
|
||||||
Console.Write($"M.I.: {sessionMessage.Index}; Role: {sessionMessage.MessageRoleText}");
|
Console.WriteLine(
|
||||||
|
$"NC [{diagnostic.GetSeverity()}] {diagnostic.GetId()}: {diagnostic.GetNotification()}; " +
|
||||||
// For SessionMessageHost.FilterFlag.NC
|
$"File: {ncLine?.FilePath}; LineNo: {ncLine?.GetLineNo()}; NC: {ncLine?.Line}");
|
||||||
var nc = sessionMessage.DirectInstantSourceCommand;
|
|
||||||
if (nc != null)
|
|
||||||
Console.Write($"Message/NC: {nc.Line}; File: {nc.FilePath}; LineNo: {nc.GetLineNo()}; ");
|
|
||||||
|
|
||||||
// For SessionMessageHost.FilterFlag.Progress or Error.
|
|
||||||
var multiTagMessage = sessionMessage.MultiTagMessage;
|
|
||||||
if (multiTagMessage != null)
|
|
||||||
Console.WriteLine($"Message/NC: {multiTagMessage.Message}");
|
|
||||||
var exception = sessionMessage.Exception;
|
|
||||||
if (exception != null)
|
|
||||||
Console.WriteLine($"Message/NC: {exception.Message}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (StepDiagnostic diagnostic in
|
||||||
|
localProjectService.StepDiagnosticProgress.Messages.ToList())
|
||||||
|
Console.WriteLine(
|
||||||
|
$"Step {diagnostic.StepIndex} [{diagnostic.GetSeverity()}] " +
|
||||||
|
$"{diagnostic.GetId()}: {diagnostic.GetNotification()}");
|
||||||
|
|
||||||
File.WriteAllLines("output-session-messages.txt",
|
File.WriteAllLines("output-session-messages.txt",
|
||||||
filteredSessionMessageList.Select(m =>
|
shellMessages.Select(m =>
|
||||||
$"Msg[{m.Index}][{m.MessageRoleText}]: {m}"));
|
$"[{m.GetSeverity()}] {m.GetId()}: {m.GetNotification()}"));
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
internal static void DemoUseSessionMessageHost2(LocalProjectService localProjectService)
|
|
||||||
{
|
|
||||||
SessionProgress sessionMessageHost = localProjectService.SessionProgress;
|
|
||||||
IMachiningChain machiningChain = localProjectService.MachiningChain;
|
|
||||||
|
|
||||||
PresentAttribute mrrPresent = typeof(MachiningStep).GetProperty(nameof(MachiningStep.Mrr_mm3ds)).GetCustomAttribute<PresentAttribute>();
|
|
||||||
string mrrUnit = mrrPresent?.TailUnitString;
|
|
||||||
string mrrFormat = mrrPresent?.DataFormatString;
|
|
||||||
PresentAttribute torquePresent = typeof(MachiningStep).GetProperty(nameof(MachiningStep.AvgAbsTorque_Nm)).GetCustomAttribute<PresentAttribute>();
|
|
||||||
string torqueUnit = torquePresent?.TailUnitString;
|
|
||||||
string torqueFormat = torquePresent?.DataFormatString;
|
|
||||||
|
|
||||||
SessionProgress.FilterFlag filterFlags =
|
|
||||||
SessionProgress.FilterFlag.Step |
|
|
||||||
SessionProgress.FilterFlag.NC |
|
|
||||||
SessionProgress.FilterFlag.Progress |
|
|
||||||
SessionProgress.FilterFlag.Error;
|
|
||||||
string filterText = null;
|
|
||||||
var filteredSessionMessageList = sessionMessageHost
|
|
||||||
.GetFliteredList(filterFlags, filterText);
|
|
||||||
|
|
||||||
foreach (var sessionMessage in filteredSessionMessageList)
|
|
||||||
{
|
|
||||||
//M.I.: Message Index.
|
|
||||||
Console.Write($"M.I.: {sessionMessage.Index}; Role: {sessionMessage.MessageRoleText}");
|
|
||||||
|
|
||||||
// For SessionMessageHost.FilterFlag.Step
|
|
||||||
var step = sessionMessage.MachiningStep;
|
|
||||||
if (step != null)
|
|
||||||
{
|
|
||||||
string[] machineCoordinateValueTexts = GetMachineCoordinateValueTexts(step, machiningChain);
|
|
||||||
var machineCoordinatesText = string.Join("; ", Enumerable.Range(0, machiningChain.McCodes.Length)
|
|
||||||
.Select(i => $"MC.{machiningChain.McCodes[i]}: {machineCoordinateValueTexts[i]}"));
|
|
||||||
Console.Write($"Time: {step.AccumulatedTime:G}; MRR = {step.Mrr_mm3ds.ToString(mrrFormat)} {mrrUnit}; Torque = {step.AvgAbsTorque_Nm?.ToString(torqueFormat)} {torqueUnit}; {machineCoordinatesText}; ");
|
|
||||||
var nc_ = sessionMessageHost.GetSourceCommand(sessionMessage);
|
|
||||||
Console.WriteLine($"Message/NC: {nc_.Line}; File: {nc_.FilePath}; LineNo: {nc_.GetLineNo()}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// For SessionMessageHost.FilterFlag.NC
|
|
||||||
var nc = sessionMessage.DirectInstantSourceCommand;
|
|
||||||
if (nc != null)
|
|
||||||
{
|
|
||||||
Console.Write($"Message/NC: {nc.Line}; File: {nc.FilePath}; LineNo: {nc.GetLineNo()}; ");
|
|
||||||
if (nc is HardNcLine ncLine)
|
|
||||||
Console.WriteLine($"T: {ncLine.T}; S: {ncLine.S}; F: {ncLine.F}; NC-Flags: {ncLine.FlagsText}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// For SessionMessageHost.FilterFlag.Progress or Error.
|
|
||||||
var multiTagMessage = sessionMessage.MultiTagMessage;
|
|
||||||
if (multiTagMessage != null)
|
|
||||||
Console.WriteLine($"Message/NC: {multiTagMessage.Message}");
|
|
||||||
var exception = sessionMessage.Exception;
|
|
||||||
if (exception != null)
|
|
||||||
Console.WriteLine($"Message/NC: {exception.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static string[] GetMachineCoordinateValueTexts(MachiningStep step, IMachiningChain machiningChain)
|
|
||||||
{
|
|
||||||
var mcTransformers = machiningChain.McTransformers;
|
|
||||||
string[] dst = new string[mcTransformers.Length];
|
|
||||||
if (mcTransformers != null)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < mcTransformers.Length; i++)
|
|
||||||
{
|
|
||||||
if (mcTransformers[i] == null)
|
|
||||||
continue;
|
|
||||||
if (mcTransformers[i] is DynamicRotation)
|
|
||||||
dst[i] = MathUtil.ToDeg(step.GetMcValue(i).Value).ToString("F4");
|
|
||||||
else
|
|
||||||
dst[i] = step.GetMcValue(i)?.ToString("F5");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
#region ShowStepPresent
|
#region ShowStepPresent
|
||||||
internal static void ShowStepPresent(
|
internal static void ShowStepPresent(
|
||||||
UserService userEnv, MachiningStep machiningStep)
|
UserService userEnv, MachiningStep machiningStep)
|
||||||
|
|||||||
141
Common/PlayerDivConfig.cs
Normal file
141
Common/PlayerDivConfig.cs
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
using Hi.Common;
|
||||||
|
using Hi.Common.XmlUtils;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace Sample.Common;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Per-user visibility flags for the Player page's divisions (charts and
|
||||||
|
/// info panels), flattened into a single all-boolean config persisted through
|
||||||
|
/// <see cref="UserConfig"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Defaults are tuned for a first-time user: the two info panels
|
||||||
|
/// (<see cref="EnableStepDiv"/> and <see cref="MessageTable"/>) are ON
|
||||||
|
/// so the Player page looks populated without having to open the
|
||||||
|
/// Division Visibility dropdown; every chart toggle starts OFF.
|
||||||
|
/// </remarks>
|
||||||
|
public class PlayerDivConfig : IMakeXmlSource
|
||||||
|
{
|
||||||
|
#region XML IO
|
||||||
|
/// <summary>
|
||||||
|
/// Registers this type's deserializer with the given <see cref="XFactory"/>
|
||||||
|
/// (or <see cref="XFactory.Default"/> when <paramref name="factory"/> is
|
||||||
|
/// <c>null</c>). Idempotent.
|
||||||
|
/// </summary>
|
||||||
|
public static void Reg(XFactory factory = null)
|
||||||
|
{
|
||||||
|
factory ??= XFactory.Default;
|
||||||
|
factory.Generators.TryAdd(XName, (xml, baseDirectory, relFile, progress, res)
|
||||||
|
=> new PlayerDivConfig(xml));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name for XML IO.
|
||||||
|
/// </summary>
|
||||||
|
public static string XName => nameof(PlayerDivConfig);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default constructor.
|
||||||
|
/// </summary>
|
||||||
|
public PlayerDivConfig() { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PlayerDivConfig"/> class from XML data.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="src">XML element containing player-div data.</param>
|
||||||
|
public PlayerDivConfig(XElement src)
|
||||||
|
{
|
||||||
|
if (src == null) return;
|
||||||
|
|
||||||
|
src.Element(nameof(EnableStripAvailabilityChart))?.Value?.SelfInvoke(
|
||||||
|
v => EnableStripAvailabilityChart = XmlConvert.ToBoolean(v));
|
||||||
|
src.Element(nameof(EnableStripRoughnessChart))?.Value?.SelfInvoke(
|
||||||
|
v => EnableStripRoughnessChart = XmlConvert.ToBoolean(v));
|
||||||
|
src.Element(nameof(ColorIndexTimeChart))?.Value?.SelfInvoke(
|
||||||
|
v => ColorIndexTimeChart = XmlConvert.ToBoolean(v));
|
||||||
|
src.Element(nameof(ForceCycleLineDiv))?.Value?.SelfInvoke(
|
||||||
|
v => ForceCycleLineDiv = XmlConvert.ToBoolean(v));
|
||||||
|
src.Element(nameof(SimSpindleMomentCycleLineDiv))?.Value?.SelfInvoke(
|
||||||
|
v => SimSpindleMomentCycleLineDiv = XmlConvert.ToBoolean(v));
|
||||||
|
src.Element(nameof(SensorSpindleMomentCycleLineDiv))?.Value?.SelfInvoke(
|
||||||
|
v => SensorSpindleMomentCycleLineDiv = XmlConvert.ToBoolean(v));
|
||||||
|
src.Element(nameof(DynamometerForceCycleLineDiv))?.Value?.SelfInvoke(
|
||||||
|
v => DynamometerForceCycleLineDiv = XmlConvert.ToBoolean(v));
|
||||||
|
src.Element(nameof(EnableStepDiv))?.Value?.SelfInvoke(
|
||||||
|
v => EnableStepDiv = XmlConvert.ToBoolean(v));
|
||||||
|
src.Element(nameof(MessageTable))?.Value?.SelfInvoke(
|
||||||
|
v => MessageTable = XmlConvert.ToBoolean(v));
|
||||||
|
src.Element(nameof(EnableDetailDiv0))?.Value?.SelfInvoke(
|
||||||
|
v => EnableDetailDiv0 = XmlConvert.ToBoolean(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public XElement MakeXmlSource(string baseDirectory, string relFile, bool exhibitionOnly)
|
||||||
|
{
|
||||||
|
return new XElement(XName,
|
||||||
|
new XElement(nameof(EnableStripAvailabilityChart), EnableStripAvailabilityChart),
|
||||||
|
new XElement(nameof(EnableStripRoughnessChart), EnableStripRoughnessChart),
|
||||||
|
new XElement(nameof(ColorIndexTimeChart), ColorIndexTimeChart),
|
||||||
|
new XElement(nameof(ForceCycleLineDiv), ForceCycleLineDiv),
|
||||||
|
new XElement(nameof(SimSpindleMomentCycleLineDiv), SimSpindleMomentCycleLineDiv),
|
||||||
|
new XElement(nameof(SensorSpindleMomentCycleLineDiv), SensorSpindleMomentCycleLineDiv),
|
||||||
|
new XElement(nameof(DynamometerForceCycleLineDiv), DynamometerForceCycleLineDiv),
|
||||||
|
new XElement(nameof(EnableStepDiv), EnableStepDiv),
|
||||||
|
new XElement(nameof(MessageTable), MessageTable),
|
||||||
|
new XElement(nameof(EnableDetailDiv0), EnableDetailDiv0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Availability strip chart (per-step timeline coloured by availability aspect).
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableStripAvailabilityChart { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Surface-roughness strip chart (per-step timeline coloured by surface-roughness aspect).
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableStripRoughnessChart { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Color-index strip chart (single-strip timeline coloured by arbitrary numeric/bool aspect).
|
||||||
|
/// </summary>
|
||||||
|
public bool ColorIndexTimeChart { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cycle-line chart of cutting force along the step's rotation cycle.
|
||||||
|
/// </summary>
|
||||||
|
public bool ForceCycleLineDiv { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cycle-line chart of simulation-derived spindle moment on spindle-rotation coordinate.
|
||||||
|
/// </summary>
|
||||||
|
public bool SimSpindleMomentCycleLineDiv { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cycle-line chart of sensor-measured spindle moment (overlay on sim moment).
|
||||||
|
/// </summary>
|
||||||
|
public bool SensorSpindleMomentCycleLineDiv { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cycle-line chart of sensor-measured force from an external dynamometer.
|
||||||
|
/// </summary>
|
||||||
|
public bool DynamometerForceCycleLineDiv { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Full / condensed step information panel (Selected Step Info).
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableStepDiv { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Session messages panel.
|
||||||
|
/// </summary>
|
||||||
|
public bool MessageTable { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Developer-only raw step-property dump panel.
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableDetailDiv0 { get; set; } = false;
|
||||||
|
}
|
||||||
173
Common/UserConfig.cs
Normal file
173
Common/UserConfig.cs
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
using Hi.Cbtr;
|
||||||
|
using Hi.Common;
|
||||||
|
using Hi.Common.XmlUtils;
|
||||||
|
using Hi.MachiningSteps;
|
||||||
|
using Hi.NcMech.Fixtures;
|
||||||
|
using Hi.NcMech.Workpieces;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace Sample.Common;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// User Configuration.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sample-owned copy of the per-GUI user configuration, kept so the
|
||||||
|
/// <see cref="DemoSessionMessage"/> step-present demo still compiles. Each
|
||||||
|
/// GUI/APP keeps its own version; the core engine package (HiNc) no longer
|
||||||
|
/// carries any GUI configuration type.
|
||||||
|
/// </remarks>
|
||||||
|
public class UserConfig : IMakeXmlSource
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Registers this type's deserializer with the given <see cref="XFactory"/>
|
||||||
|
/// (or <see cref="XFactory.Default"/> when <paramref name="factory"/> is
|
||||||
|
/// <c>null</c>). Idempotent.
|
||||||
|
/// </summary>
|
||||||
|
public static void Reg(XFactory factory = null)
|
||||||
|
{
|
||||||
|
factory ??= XFactory.Default;
|
||||||
|
factory.Generators.TryAdd(XName, (xml, baseDirectory, relFile, progress, res)
|
||||||
|
=> new UserConfig(xml, baseDirectory));
|
||||||
|
}
|
||||||
|
#region XML IO
|
||||||
|
/// <summary>
|
||||||
|
/// Name for XML IO.
|
||||||
|
/// </summary>
|
||||||
|
public static string XName => nameof(UserConfig);
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UserConfig"/> class from XML data.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="src">XML element containing configuration data</param>
|
||||||
|
/// <param name="baseDirectory">Base directory for resolving relative paths</param>
|
||||||
|
public UserConfig(XElement src, string baseDirectory)
|
||||||
|
{
|
||||||
|
if (src == null) return;
|
||||||
|
|
||||||
|
src.Element(nameof(ShowPhysicsOptions))?.Value?.SelfInvoke(
|
||||||
|
v => ShowPhysicsOptions = XmlConvert.ToBoolean(v));
|
||||||
|
src.Element(nameof(LanguageCode))?.Value?.SelfInvoke(v => LanguageCode = v);
|
||||||
|
src.Element(nameof(EnableFullControl))?.Value?.SelfInvoke(
|
||||||
|
v => EnableFullControl = XmlConvert.ToBoolean(v));
|
||||||
|
|
||||||
|
src.Element(nameof(GraphicCacheLowerLimitMb))?.Value?.SelfInvoke(
|
||||||
|
v => GraphicCacheLowerLimitMb = XmlConvert.ToDouble(v));
|
||||||
|
src.Element(nameof(GraphicCacheUpperLimitMb))?.Value?.SelfInvoke(
|
||||||
|
v => GraphicCacheUpperLimitMb = XmlConvert.ToDouble(v));
|
||||||
|
src.Element(nameof(GraphicCacheMb))?.Value?.SelfInvoke(
|
||||||
|
v => GraphicCacheMb = XmlConvert.ToInt64(v));
|
||||||
|
|
||||||
|
src.Element(nameof(DisplayedStepPresentKeyList))?.SelfInvoke(ee =>
|
||||||
|
{
|
||||||
|
DisplayedStepPresentKeyList = ee.Elements("Item").Select(e => e.Value).ToList();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load FixtureSetupDisplayeeConfig
|
||||||
|
src.Element(nameof(FixtureSetupDisplayeeConfig))?.SelfInvoke(e =>
|
||||||
|
{
|
||||||
|
FixtureSetupDisplayeeConfig = new FixtureEditorDisplayeeConfig(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load EquipmentWorkpieceSetupDisplayeeConfig
|
||||||
|
src.Element(nameof(EquipmentWorkpieceSetupDisplayeeConfig))?.SelfInvoke(e =>
|
||||||
|
{
|
||||||
|
EquipmentWorkpieceSetupDisplayeeConfig = new WorkpieceEditorDisplayeeConfig(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load PlayerDivConfig
|
||||||
|
src.Element(nameof(PlayerDivConfig))?.SelfInvoke(e =>
|
||||||
|
{
|
||||||
|
PlayerDivConfig = new PlayerDivConfig(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public XElement MakeXmlSource(string baseDirectory, string relFile, bool exhibitionOnly)
|
||||||
|
{
|
||||||
|
XElement dst = new XElement(XName,
|
||||||
|
new XElement(nameof(ShowPhysicsOptions), ShowPhysicsOptions),
|
||||||
|
new XElement(nameof(LanguageCode), LanguageCode),
|
||||||
|
new XElement(nameof(EnableFullControl), EnableFullControl),
|
||||||
|
new XElement(nameof(GraphicCacheLowerLimitMb), GraphicCacheLowerLimitMb),
|
||||||
|
new XElement(nameof(GraphicCacheUpperLimitMb), GraphicCacheUpperLimitMb),
|
||||||
|
new XElement(nameof(GraphicCacheMb), GraphicCacheMb),
|
||||||
|
new XElement(nameof(DisplayedStepPresentKeyList),
|
||||||
|
DisplayedStepPresentKeyList.Select(v => new XElement("Item", v))),
|
||||||
|
new XElement(nameof(FixtureSetupDisplayeeConfig),
|
||||||
|
FixtureSetupDisplayeeConfig?.MakeXmlSource(baseDirectory, relFile, exhibitionOnly)),
|
||||||
|
new XElement(nameof(EquipmentWorkpieceSetupDisplayeeConfig),
|
||||||
|
EquipmentWorkpieceSetupDisplayeeConfig?.MakeXmlSource(baseDirectory, relFile, exhibitionOnly)),
|
||||||
|
PlayerDivConfig?.MakeXmlSource(baseDirectory, relFile, exhibitionOnly)
|
||||||
|
);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets whether to show physics options in the UI.
|
||||||
|
/// </summary>
|
||||||
|
public bool ShowPhysicsOptions { get; set; } = false;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the language code for the application UI.
|
||||||
|
/// </summary>
|
||||||
|
public string LanguageCode { get; set; } = "en";
|
||||||
|
/// <summary>
|
||||||
|
/// Enable Full control of the application.
|
||||||
|
/// Eanble System.Diagnostics.Process in GUI Script Command.
|
||||||
|
/// Not used yet.
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableFullControl { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the lower limit of graphic cache in megabytes.
|
||||||
|
/// </summary>
|
||||||
|
public double GraphicCacheLowerLimitMb { get; set; } = 10;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the upper limit of graphic cache in megabytes.
|
||||||
|
/// </summary>
|
||||||
|
public double GraphicCacheUpperLimitMb { get; set; } = 1200;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the graphic cache size in megabytes.
|
||||||
|
/// </summary>
|
||||||
|
public long GraphicCacheMb
|
||||||
|
{
|
||||||
|
get => CubeTree.DispCacheMb;
|
||||||
|
set => CubeTree.DispCacheMb = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Step infomation key list to show.
|
||||||
|
/// </summary>
|
||||||
|
public List<string> DisplayedStepPresentKeyList { get; set; } = new List<string>([
|
||||||
|
nameof(MachiningStep.StepIndex),
|
||||||
|
nameof(MachiningStep.FileNo), nameof(MachiningStep.LineNo),
|
||||||
|
nameof(MachiningStep.FilePath),nameof(MachiningStep.EndTimecode),
|
||||||
|
nameof(MachiningStep.LineText),nameof(MachiningStep.FlagsText),
|
||||||
|
nameof(MachiningStep.ToolId),
|
||||||
|
nameof(MachiningStep.SpindleSpeed_rpm),nameof(MachiningStep.Feedrate_mmdmin),
|
||||||
|
nameof(MachiningStep.Mrr_mm3ds),
|
||||||
|
nameof(MachiningStep.AvgAbsTorque_Nm),
|
||||||
|
]);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Configuration for FixtureSetupDisplayee
|
||||||
|
/// </summary>
|
||||||
|
public FixtureEditorDisplayeeConfig FixtureSetupDisplayeeConfig { get; set; } = new FixtureEditorDisplayeeConfig();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Configuration for EquipmentWorkpieceSetupDisplayee
|
||||||
|
/// </summary>
|
||||||
|
public WorkpieceEditorDisplayeeConfig EquipmentWorkpieceSetupDisplayeeConfig { get; set; } = new WorkpieceEditorDisplayeeConfig();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Per-user visibility flags for the Player page's divisions (charts and info panels).
|
||||||
|
/// Persisted alongside the rest of this <see cref="UserConfig"/>.
|
||||||
|
/// </summary>
|
||||||
|
public PlayerDivConfig PlayerDivConfig { get; set; } = new PlayerDivConfig();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default constructor
|
||||||
|
/// </summary>
|
||||||
|
public UserConfig() { }
|
||||||
|
}
|
||||||
160
Common/UserService.cs
Normal file
160
Common/UserService.cs
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
using Hi.Common;
|
||||||
|
using Hi.Common.XmlUtils;
|
||||||
|
using Hi.Licenses;
|
||||||
|
using Hi.MachiningSteps;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Sample.Common;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// User Service.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sample-owned copy, kept so the <see cref="DemoSessionMessage"/> step-present
|
||||||
|
/// demo still compiles. Each GUI/APP keeps its own version; the core engine
|
||||||
|
/// package (HiNc) no longer carries this GUI service type.
|
||||||
|
/// </remarks>
|
||||||
|
public class UserService : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the application configuration.
|
||||||
|
/// </summary>
|
||||||
|
public UserConfig UserConfig { get; set; } = new UserConfig();
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the path to the application configuration file.
|
||||||
|
/// </summary>
|
||||||
|
public string UserConfigPath { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether physics features are enabled based on configuration and license.
|
||||||
|
/// </summary>
|
||||||
|
public bool EnablePhysics =>
|
||||||
|
UserConfig.ShowPhysicsOptions && IsPhysicsLicensed;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether advanced physics features are licensed.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsPhysicsLicensed => License.IsLoggedIn(AuthFeature.AdvancedPhysics);
|
||||||
|
|
||||||
|
//runtime properties are not in the category of canonical IO.
|
||||||
|
#region Runtime Property
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
LooseRunner SaveConfigLooseRunner;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the currently selected item in the application.
|
||||||
|
/// </summary>
|
||||||
|
public object SelectedItem { get; set; }
|
||||||
|
private bool disposedValue;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UserService"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">The logger instance.</param>
|
||||||
|
public UserService(ILogger logger) { _logger = logger; SaveConfigLooseRunner = new LooseRunner(logger); }
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UserService"/> class with the specified configuration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="appConfig">The application configuration.</param>
|
||||||
|
/// <param name="logger">The logger instance.</param>
|
||||||
|
public UserService(UserConfig appConfig, ILogger logger) : this(logger) { UserConfig = appConfig; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves the user configuration to the file specified by <see cref="UserConfigPath"/>.
|
||||||
|
/// </summary>
|
||||||
|
public void SaveUserConfig()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (UserConfigPath != null)
|
||||||
|
UserConfig.MakeXmlSourceToFile(UserConfigPath);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger?.LogError(ex, "{Message}", ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Schedules a loose save of the user configuration using a LooseRunner.
|
||||||
|
/// </summary>
|
||||||
|
public void LooseSaveUserConfig()
|
||||||
|
{
|
||||||
|
SaveConfigLooseRunner.TryRun(token => SaveUserConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
#region step present
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets additional step presentation access configurations.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, PresentAccess> AdditionalStepPresentAccess { get; set; } = new Dictionary<string, PresentAccess>();
|
||||||
|
/// <summary>
|
||||||
|
/// StepPresentAccessDictionary.
|
||||||
|
/// Read only.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, PresentAccess> StepPresentAccessDictionary
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var originalPresentAccessDictionary = typeof(MachiningStep).GetProperties()
|
||||||
|
.Where(p => p.GetCustomAttribute<PresentAttribute>() != null)
|
||||||
|
.ToDictionary(prop => prop.Name, prop =>
|
||||||
|
new PresentAccess(prop.GetCustomAttribute<PresentAttribute>(),
|
||||||
|
step => prop.GetValue(step)));
|
||||||
|
var presentAccessDictionary = new Dictionary<string, PresentAccess>(
|
||||||
|
AdditionalStepPresentAccess.Concat(originalPresentAccessDictionary));
|
||||||
|
return presentAccessDictionary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Candidate Step Present Key List for display.
|
||||||
|
/// Read only.
|
||||||
|
/// </summary>
|
||||||
|
public List<string> CandidateStepPresentKeyList => StepPresentAccessDictionary.Keys.ToList();
|
||||||
|
/// <summary>
|
||||||
|
/// StepPresentAccessList for display.
|
||||||
|
/// Read only.
|
||||||
|
/// </summary>
|
||||||
|
public List<KeyValuePair<string, PresentAccess>> DisplayedStepPresentAccessList
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var displayedStepPresentKeyList = UserConfig.DisplayedStepPresentKeyList;
|
||||||
|
List<KeyValuePair<string, PresentAccess>> dst
|
||||||
|
= new List<KeyValuePair<string, PresentAccess>>(
|
||||||
|
displayedStepPresentKeyList.Count);
|
||||||
|
var stepPresentAccessDictionary = StepPresentAccessDictionary;
|
||||||
|
foreach (var key in displayedStepPresentKeyList)
|
||||||
|
{
|
||||||
|
if (stepPresentAccessDictionary.TryGetValue(
|
||||||
|
key, out var access))
|
||||||
|
{
|
||||||
|
dst.Add(new KeyValuePair<string, PresentAccess>(key, access));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!disposedValue)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
SaveConfigLooseRunner.Dispose();
|
||||||
|
}
|
||||||
|
disposedValue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
||||||
|
Dispose(disposing: true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@
|
|||||||
using Hi.Common.Messages;
|
using Hi.Common.Messages;
|
||||||
using Hi.HiNcKits;
|
using Hi.HiNcKits;
|
||||||
using Hi.MachiningProcs;
|
using Hi.MachiningProcs;
|
||||||
|
using Hi.NcParsers;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -37,17 +38,22 @@ public static class DemoUseMachiningProject
|
|||||||
Console.WriteLine($"Set message event.");
|
Console.WriteLine($"Set message event.");
|
||||||
|
|
||||||
using StreamWriter writer = new StreamWriter("msg.txt");
|
using StreamWriter writer = new StreamWriter("msg.txt");
|
||||||
//show message if something abnormal.
|
//show message if something abnormal, from each partitioned message sink:
|
||||||
localProjectService.SessionProgress.CollectionItemAdded += pack =>
|
//shell (session lifecycle), NC diagnostics, and step-anchored diagnostics.
|
||||||
|
void LogIfAbnormal(IMessage message, ISentenceCarrier sentenceCarrier)
|
||||||
{
|
{
|
||||||
if (pack.Tags.Contains(MessageFlag.Warning.ToString()) ||
|
var severity = message.GetSeverity();
|
||||||
pack.Tags.Contains(MessageFlag.Error.ToString()) ||
|
if (severity != Severity.Warning && severity != Severity.Error)
|
||||||
pack.Tags.Contains(MessageFlag.Exception.ToString()))
|
return;
|
||||||
{
|
var ncLine = sentenceCarrier?.GetSentence()?.FirstIndexedFileLine;
|
||||||
var sourceCommand = pack.SourceCommand;
|
writer.WriteLine($"{message.GetNotification()} At \"{ncLine?.FilePath}\" (Line {ncLine?.GetLineNo()}) \"{ncLine?.Line}\"");
|
||||||
writer.WriteLine($"{pack.Message} At \"{sourceCommand?.FilePath}\" (Line {sourceCommand?.GetLineNo()}) \"{sourceCommand?.Line}\"");
|
|
||||||
}
|
}
|
||||||
};
|
localProjectService.OnShellMessageAdded += (index, message)
|
||||||
|
=> LogIfAbnormal(message, null);
|
||||||
|
localProjectService.NcDiagnosticProgress.MessageAdded += (index, diagnostic)
|
||||||
|
=> LogIfAbnormal(diagnostic, diagnostic.SentenceCarrier);
|
||||||
|
localProjectService.StepDiagnosticProgress.MessageAdded += (index, diagnostic)
|
||||||
|
=> LogIfAbnormal(diagnostic, diagnostic.SentenceCarrier);
|
||||||
Console.WriteLine($"Set machining step event.");
|
Console.WriteLine($"Set machining step event.");
|
||||||
//show MRR.
|
//show MRR.
|
||||||
localProjectService.SessionShell.SessionStepBuilt += (preStep, curStep) =>
|
localProjectService.SessionShell.SessionStepBuilt += (preStep, curStep) =>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user