Table of Contents

Session Info Panel

On the Execution page the panel under the canvas is Session Info (SessionInfoPanel.vue). It has no title row. The nav bar's Center-Down button (data-testid="session-info-toggle", tooltip Toggle the Session Info panel) shows and hides it through the server flag sessionInfo. Center-Top shows the canvas (showCanvas, this browser). Either pane can fill the center column; both off, the column is not drawn. Message counts sit beside the tab label (inline-label); no tab carries an icon.

The same panel holds the three strip charts as tabs ahead of the message lists, and a last Tabs tab whose boxes (sessionInfoTabs, this browser) choose which of the content tabs the bar shows. Availability is offered only while physics options are on.

Session messages are partitioned by kind into four sinks on LocalProjectService (obtained via dependency injection):

The panel surfaces each sink in its own tab, so one tab holds one message kind. ResetRuntime — which a project change runs — empties the first three, so each of them holds the current project only; the manipulation sink is outside that sweep, cleared only at the start of the conversion or optimization run that fills it, and its rows therefore survive a project change. Every Warning and Error of the four sinks is also copied into the service log as it arrives, capped per message id, where it outlives both clearings — see Log Viewer Page.

Layout

  • Tab Bar (no icons; a message tab's count sits beside its label, drawn only while its sink holds messages)
    • Color Index — the Color Index Time Chart
    • Availability — the Availability Chart, only while physics options are on
    • Surface Roughness — the Surface Roughness Chart
    • Shell Tab
    • NC Diagnostics Tab
    • Step Diagnostics Tab
    • NC Manipulation Tab
    • Tabs — Show these tabs, one checkbox per content tab
  • Per Message Tab Content
    • Filter Toolbar
      • Severity Filter Dropdown
      • Category Filter Dropdown
      • Message Text Filter Input — keeps a row whose notification, id, detail or anchor holds the text, with letter case, diacritics and character width ignored and katakana found by their hiragana (Typing and Searching)
      • Reset Button (this tab's three filters, nothing else)
      • Export Button
      • Matched / Total Badge (also the tab's hub connection indicator)
    • Message Table

Message Table (per message tab)

Each message tab renders its sink's message list — Messages, Messages, or Diagnostics for the two NC-diagnostic sinks — as rows of:

  • Severity (colour-coded via GetSeverity())
  • Anchor — the kind-specific position: none for shell messages, the NC sentence ordinal (Sn <n>) for both the play-time and the manipulation NC diagnostics, and the motion step with its sentence ordinal (S<step> · Sn <n>) for step diagnostics; an NC diagnostic raised at pipeline level rather than at a source block carries none. A Collision--Detected is anchored to the index its pose's step takes and said at the detection, before that step is built — a play that pauses on failure pauses on it — so it can name an index the strip holds no step at, or, after a stop and a start without a reset, an index a later step took; so can a licence or lease refusal said before a step is granted (MachiningStep--LicenseCapReached and its kin, which hold the play), a Player-Run--Fault, and a Step-Task--Fault, whose step's building failed. Their rows check the step: when the step does not carry the message's sentence, the cell shows the message's own NC line instead, marked step not built (<file>:<line> · step not built, or Sn <n> · step not built when the sentence has no file line), and its tooltip says which case it is — the play paused before building the step, the run ended before building it, a stop dropped it or building it failed, or a later step took the index — and ends with the S<step> · Sn <n> form; a row asks GET api/NcProgram/sentence-of-step once it comes into view, and asks again as the strip moves. A step the pipeline is still filling, or the one a running play is building, keeps its S<step> · Sn <n>. The other step messages — a script's, a tool change's, a line end's, an empty spindle's — are anchored to the next built step by design and keep S<step> · Sn <n> unchecked. A stroke-limit report names no sentence: it is anchored to the step it checked, or to the next built step when the motion it checked built none, and its row shows S<step> alone, unchecked too. The CSV export and the text filter keep the row's anchor — S<step> · Sn <n>, or S<step> on a row that names no sentence, such as a stroke-limit report's — rather than the step not built text.
  • Message — GetCategory(), GetId() and GetNotification()

Only take the last filtered elements (e.g. 500–1000) for user experience. Find the usage example in the code:

internal static void DemoUseSessionMessageHost(LocalProjectService localProjectService)
{
    // 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.

    ShellProgress shellProgress = localProjectService.ShellProgress;
    List<IMessage> shellMessages = shellProgress == null
        ? new List<IMessage>() : shellProgress.Messages.ToList();
    foreach (IMessage message in shellMessages)
        Console.WriteLine(
            $"Shell [{message.GetSeverity()}] {message.GetId()}: {message.GetNotification()}");

    foreach (NcDiagnostic diagnostic in
        localProjectService.NcDiagnosticProgress.Diagnostics.ToList())
    {
        var ncLine = diagnostic.SentenceCarrier?.GetSentence()?.FirstIndexedFileLine;
        Console.WriteLine(
            $"NC [{diagnostic.GetSeverity()}] {diagnostic.GetId()}: {diagnostic.GetNotification()}; " +
            $"File: {ncLine?.FilePath}; LineNo: {ncLine?.GetLineNo()}; NC: {ncLine?.Line}");
    }

    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",
        shellMessages.Select(m =>
        $"[{m.GetSeverity()}] {m.GetId()}: {m.GetNotification()}"));
}

Add the update-table event per sink: MessageAdded / MessageAdded, and for the session-scoped shell sink the app-lifetime bridge OnShellMessageAdded (with the matching Cleared events). The updating process has to be called by Loose Manner for user experience.

Note

The message display should be real-time.

Behavior of Export Button

Every message tab has its own Export, and it carries that tab's sink alone. It writes the rows the tab is holding — the recent window pulled from that sink, narrowed by that tab's severity, category and text filters — as a CSV of Index,Count,Severity,Category,Id,Anchor,Notification,Detail, named after the sink it came from. It is disabled while the filters match nothing.

SignalR Implementation (Webapi Only)

One hub per sink — /shellMessageHub, /ncDiagnosticHub, /stepDiagnosticHub, /ncManipulationDiagnosticHub — each with a GetMessages(int limit) pull returning MessagesUpdate { messages, totalCount }. A per-sink broadcast service subscribes its sink's MessageAdded/Cleared and raises a coalesced MessagesChanged notification via LooseRunner; the client re-pulls the recent window on each notification (loss-free regardless of how many appends coalesced). The client components connect to the hubs they display to receive real-time updates.

Source Code Path

See HiNC App Anatomy for git repository links.

  • wwwroot-src/src/components/execution/SessionInfoPanel.vue (the tabbed Session Info panel: strip charts and message lists)
  • wwwroot-src/src/components/execution/SessionMessageTab.vue + MessageRow.vue (per-tab list)
  • wwwroot-src/src/composables/useStepAnchorStatus.ts (whether a step row's step carries the message's sentence)
  • wwwroot-src/src/composables/useSessionSinkHub.ts (the four hub composables)
  • Execution/SessionSinkHub.cs (the SignalR hub base; one hub per sink)
  • Execution/SessionSinkBroadcastService.cs + ShellMessageBroadcastService.cs, NcDiagnosticBroadcastService.cs, StepDiagnosticBroadcastService.cs, NcManipulationDiagnosticBroadcastService.cs (subscribe-and-rebroadcast)
  • Execution/SessionSinkDtos.cs (typed DTOs)

See Also