This repository has been archived on 2026-10-11. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
HiNC-2025-win-desktop-Deploy/App/wwwroot/HiAPI-docsite/anatomy/general-setup/hidden-controllers.html
T
2026-09-09 17:35:23 +08:00

611 lines
39 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hidden Controller Branches | HiAPI-C# 2025 </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Hidden Controller Branches | HiAPI-C# 2025 ">
<link rel="icon" href="../../img/HiAPI.favicon.ico">
<link rel="stylesheet" href="../../public/docfx.min.css">
<link rel="stylesheet" href="../../public/main.css">
<meta name="docfx:navrel" content="../../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../../">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../../index.html">
<img id="logo" class="svg" src="../../img/HiAPI.logo.png" alt="">
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="Anatomy-HiddenControllers">
<h1 id="hidden-controller-branches">Hidden Controller Branches</h1>
<p>Two Control-Tree nodes on the General Setup page are absent from a fresh installation: <strong>CSV
Controller</strong> and <strong>CL Controller</strong>, on <code>/general-setup</code> under the ids <code>equipment/controller-csv</code> and
<code>equipment/controller-cl</code>. Each is the entire editing face of one resident non-brand runner suit —
the CSV control-table pipeline and the NX-CL (CLSF) pipeline — and each is minted only when its
device-local Preference checkbox is on or the current URL targets it. This page is the answer to
&ldquo;why is that node not in the tree&rdquo;, because the equipment tree withholds a node in two different ways
and only one of them can be talked out of it.</p>
<div class="IMPORTANT">
<h5>Important</h5>
<p>Anatomy makes no claim that any id named here is stable across versions. The migration hop that
keeps an older <code>?tree=</code> value resolving is described in
<a class="xref" href="../platform/tree-ids-and-routes.html">Tree Ids and Routes</a>.</p>
</div>
<h2 id="two-kinds-of-invisibility">Two Kinds of Invisibility</h2>
<table>
<thead>
<tr>
<th style="text-align: left;"></th>
<th>Preference-gated</th>
<th>Brand-gated</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">Which nodes</td>
<td><code>equipment/controller-csv</code>, <code>equipment/controller-cl</code></td>
<td>every gated leaf under <code>equipment/controller</code></td>
</tr>
<tr>
<td style="text-align: left;">What decides</td>
<td>a checkbox stored in the browser</td>
<td>the active runner's dependency list</td>
</tr>
<tr>
<td style="text-align: left;">Where the decision lives</td>
<td>one device</td>
<td>the project</td>
</tr>
<tr>
<td style="text-align: left;">Reachable by a link anyway</td>
<td>yes, and deliberately</td>
<td>no</td>
</tr>
<tr>
<td style="text-align: left;">What a link to it does</td>
<td>mints the node and selects it</td>
<td>nothing at all</td>
</tr>
</tbody>
</table>
<p>The distinction is not a matter of degree. A preference-gated node exists in the code that builds
the tree and is simply not pushed; the same build reads the URL, so naming the node in a link is
enough to bring it back for that visit. A brand-gated node has no such second door: the branch
builder never creates it, and the selection code refuses an id the built tree does not carry, so
there is nothing for a link to select. Which leaf that branch grows on which brand, and the snapshot
flag behind each one, is <a class="xref" href="controller/brand-matrix.html">Brand Matrix</a>.</p>
<h2 id="preference-gated-the-two-runner-suit-nodes">Preference-Gated: The Two Runner-Suit Nodes</h2>
<p>The equipment tree host mints each of the two nodes when <strong>a project is open</strong> and <strong>either</strong> the
node's checkbox is on <strong>or</strong> the route's tree id begins with that node's id. All three parts matter.</p>
<p><strong>With no project open neither node is built</strong>, whatever the checkboxes say — the same guard that
keeps the Controller branch childless before a project is loaded. The consequence is not a dead end:
loading a project bumps the layout's project epoch, which destroys and rebuilds the page, and the
rebuilt host runs the build again and then adopts whatever <code>?tree=</code> the URL still carries. A link
opened against an empty application therefore lands on its node once a project is opened, without
the link being touched.</p>
<p><strong>The checkboxes are device-local.</strong> Both are held in one browser-storage record of view
preferences, off by default, written back a moment after each flip, and never sent to the server —
so the setting belongs to a browser rather than to a user account or to a project. They are the
<strong>CSV Controller</strong> and <strong>CL Controller</strong> entries of the app menu bar's Preference dropdown, described
in <a class="xref" href="../shell/preference-menu.html">Preference Menu</a>.</p>
<p><strong>Only the route reveals — not the persisted last selection.</strong> The host also remembers the last node
selected on each tree page, and that memory deliberately mints nothing: the landing selection is
honoured only when the id it names is already in the built tree, and falls back to the <code>equipment</code>
group root when it is not. Reveal-by-route has to happen while the tree is being built, because the
code that adopts a <code>?tree=</code> id afterwards refuses an id the tree lacks.</p>
<h3 id="switching-a-box-off-while-standing-on-its-node">Switching a box off while standing on its node</h3>
<p>The host watches both checkboxes and rebuilds the whole equipment tree when either flips. Before the
rebuild it checks whether the current selection is one of the nodes that just lost its box, and when
it is, it does two things in this order:</p>
<ol>
<li>Replaces the URL's <code>tree</code> query with <code>equipment</code>.</li>
<li>Moves the selection to the <code>equipment</code> group root.</li>
</ol>
<p>Only then does the tree rebuild. The order is the point: the URL already mirrors the selection, and
the URL is exactly what reveals an unchecked node, so a selection left standing there would leave its
id in the query, and the next build's prefix test would re-mint the node that was just switched off.
The reader lands on the General Setup group panel, whose clickable child list no longer carries the
row. The selection is moved directly rather than through the host's switch request, which would
matter only for a panel registering the before-switch gate; neither of these two does.</p>
<p>Switching a box off while the selection is elsewhere takes no such detour — the rebuild simply drops
the node from the tree and from the group panel's child list.</p>
<h3 id="what-the-two-nodes-are-not">What the two nodes are not</h3>
<p>Both are childless leaves. Neither declares a child builder, so nothing grows beneath them; neither
registers a content view, so the General Setup content column keeps its own empty hint for both; and
neither panel reports a structural change, so nothing either panel does rebuilds any part of the
tree. There is no Object-Management menu on either: a CSV or CL pipeline is not loaded, pasted or
saved as a file of its own the way a brand controller is.</p>
<h2 id="brand-gated-the-node-that-was-never-minted">Brand-Gated: The Node That Was Never Minted</h2>
<p>Under <code>equipment/controller</code> the node set is grown from a snapshot of the active NC runner, and a
leaf whose backing dependency that runner does not resolve is never created. Nothing reveals it. A
link naming such an id — <code>equipment/controller/program-data/frames</code> on a project running a Fanuc
runner, say — reaches the host, finds no such node in the built tree, and is dropped: the selection
is left as it was, the URL keeps the id it was given, and no redirect and no message follow. On a
first load that means the editor row shows its own hint, <em>&quot;Select an item in the Control Tree to edit
it here.&quot;</em>, under a tree in which the node the link names is simply not present.</p>
<p>The two behaviours meet at the same line of code from opposite sides. The runner-suit nodes are read
out of the URL <strong>while the tree is built</strong>, so by the time that check runs they exist; a brand-gated
leaf is not, so the check is the end of the road for it. That is why a checkbox can be overruled by a
link and a runner cannot.</p>
<h2 id="what-the-preference-captions-mean">What the Preference Captions Mean</h2>
<p>Under each checkbox sits a caption reading either <em>&ldquo;This project plays CSV&rdquo;</em> / <em>&ldquo;This project plays
CL&rdquo;</em> or <em>&ldquo;Not used by this project&rdquo;</em>. It is the informed-choice half of the design: the menu answers
whether the loaded project plays that kind, so the decision to show a node is made with evidence
rather than by trial. The caption is read when the Preference dropdown opens rather than on page
load, and both runner snapshots are fetched together; with no project open both captions are blank,
and a snapshot that fails to load leaves its own caption blank rather than asserting either answer.</p>
<p>The evidence is a scan of the loaded project, per kind:</p>
<ul>
<li>A mission <strong>Program File</strong> command whose effective kind is that kind — its explicit kind, or, for
the default <em>Auto</em>, the kind detected from the file extension: <code>.cl</code>, <code>.cls</code> and <code>.clsf</code> are CL,
<code>.csv</code> is CSV, and every other extension is brand NC code
(<a class="xref" href="../../api/Hi.MachiningProcs.NcKindUtil.html#Hi_MachiningProcs_NcKindUtil_DetectByPath_">DetectByPath</a><small>(API)</small>).</li>
<li>A mission <strong>script</strong> command whose text contains <code>CsvFile(</code> or <code>ClFile(</code>. It is a bare substring
test rather than a list of verbs. The play verbs end in it —
<a class="xref" href="../../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_PlayCsvFile_">PlayCsvFile</a><small>(API)</small> and
<a class="xref" href="../../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_PlayClFile_">PlayClFile</a><small>(API)</small> — and on the CSV side so do
the two sensor-mapping verbs,
<a class="xref" href="../../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_MapSingleByCsvFile_">MapSingleByCsvFile</a><small>(API)</small> and
<a class="xref" href="../../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_MapSeriesByCsvFile_">MapSeriesByCsvFile</a><small>(API)</small>, so a script that
only maps recorded telemetry onto steps counts as CSV evidence though it plays no control table.
The CL side carries no such neighbour: every member whose call text ends in <code>ClFile(</code> plays or runs
a CLSF file.</li>
<li>For CL only, a machining chain that is a <a class="xref" href="../../api/HiMachining.Milling.ClMillingDevice.html">ClMillingDevice</a>, since a
pure-CL project plays nothing else.</li>
</ul>
<p>Three properties of that scan are easy to guess wrong. It walks the whole mission, the entries of a
nested list command included, and it walks <strong>through</strong> each command's enable wrapper without reading
it — a Program File command that is switched off still counts as evidence. The script test cuts the
other way too: a play routed through the generic NC entry point with a <code>.csv</code> path is deliberately
not matched, because a bare <code>.csv</code> appears in step and shot output templates far more often than in
play paths. And the answer feeds the caption and nothing else — <strong>usage evidence mints no node.</strong>
The tree is built from the checkbox and the route, and from nothing the scan reports.</p>
<h2 id="how-both-panels-edit">How Both Panels Edit</h2>
<p>Neither node belongs to the Controller branch, so that branch's
<a class="xref" href="controller/editing-contract.html">Editing Contract</a> does not govern them. Both panels
nonetheless follow most of its shape, and the places they do not are worth naming.</p>
<p><strong>Shared with the contract.</strong> Each panel fetches its own snapshot once on mount and owns no store.
Each opens with two guards, in order: <em>&quot;No project loaded.&quot;</em> from the snapshot's own project flag,
then a line naming the absent config — <em>&quot;No CSV column config on the CSV runner.&quot;</em> or <em>&quot;No CLSF
config on the CL runner.&quot;</em> Every control commits on its own, with no save button and no dirty
marker. A failed write raises one negative toast, three seconds, composed as the panel's localized
context followed by the server's own English sentence, with a console line beside it, and leaves no
inline error state behind once it expires. Both REST surfaces answer a missing config inside a
success envelope rather than with an error status, and the shared write helper turns that envelope
into a thrown error; the read helper inspects no envelope, and neither endpoint has a non-200 path,
so a read fails only on transport. A failed read therefore leaves the empty snapshot in place and the
panel renders its <em>&quot;No project loaded.&quot;</em> line — the same body an absent project produces, with the
toast as the only signal that the two differ.</p>
<p><strong>Where they part from it.</strong> The CSV panel is not optimistic: its text fields are bound to a local
draft, so the screen already shows the new text, and the request is awaited before the panel's
server mirror is updated; a failure restores the field from that mirror. The CL panel is optimistic
in the contract's own shape, assigning first and restoring on failure, and its two numeric fields are
the shared numeric widget, committing on blur or on Enter and never per keystroke; the full widget
contract is <a class="xref" href="../widget/numeric-input.html">Numeric Input</a>.</p>
<p><strong>Both panels guard on equality, and the guard is the panel's rather than the widget's.</strong> Every
commit handler on both — the CSV tag fields, the two CL rates and the tool-house toggle — compares
the incoming value against the fetched server mirror first and returns when the two match, so
committing an untouched field, or blurring after an Enter that already succeeded, sends nothing.
That is the departure from the Controller branch, whose numeric leaves carry no such comparison and
lean on the shared widget alone, and the widget emits on every blur and every Enter. The one control
across the two panels with no such comparison is the CL chip field.</p>
<h2 id="csv-controller">CSV Controller</h2>
<p>The node is the face of the project's resident CSV runner suit
(<a class="xref" href="../../api/Hi.MachiningProcs.MachiningProject.html#Hi_MachiningProcs_MachiningProject_CsvRunnerSuit">CsvRunnerSuit</a>), a whole runner suit constructed alongside
the brand one and never absent from a loaded project. Its runner is a
<a class="xref" href="../../api/Hi.NcParsers.SoftNcRunner.html">SoftNcRunner</a> assembled as the CSV pipeline by the factory
<a class="xref" href="../../api/Hi.Numerical.CsvParsers.GeneralCsvRunner.html">GeneralCsvRunner</a>, and it replays a CSV control table. A project file
that stores the column configuration flat, outside any suit, has that element migrated into the
suit's pipeline as it loads, so such a file keeps its tags.</p>
<p>The whole face is one flat configuration, <a class="xref" href="../../api/Hi.Numerical.CsvParsers.CsvRunnerConfig.html">CsvRunnerConfig</a> — no brand
presets, no per-case tables and no native parameter form, which is why the node is a leaf rather than
a branch. The panel's caption says what it edits: <em>&quot;Column tags of the CSV control table (matched
against the header line). Played by a mission Program File of CSV kind or a script's
<code>PlayCsvFile(&quot;…&quot;)</code>.&quot;</em> The header line is the file's first row, split on commas; each title then has
quote characters stripped from its two ends and is trimmed of whitespace, in that order, so a title
whose opening quote sits behind a space keeps that quote and never matches its tag.</p>
<table>
<thead>
<tr>
<th>Field label</th>
<th>Default tag</th>
<th>What reads it</th>
</tr>
</thead>
<tbody>
<tr>
<td>Machine coordinate prefix</td>
<td><code>MC.</code></td>
<td>the machine-coordinate columns, composed as the prefix plus <code>X</code>, <code>Y</code>, <code>Z</code>, <code>A</code>, <code>B</code>, <code>C</code></td>
</tr>
<tr>
<td>Cutter location prefix</td>
<td><code>CL.</code></td>
<td>nothing in the shipped pipeline</td>
</tr>
<tr>
<td>Tool id column</td>
<td><code>ToolId</code></td>
<td>the tool-change section</td>
</tr>
<tr>
<td>Spindle speed column (rpm)</td>
<td><code>SpindleSpeed_rpm</code></td>
<td>the spindle section</td>
</tr>
<tr>
<td>Spindle direction column</td>
<td><code>Spd.Dir.</code></td>
<td>the spindle section, parsed as a direction name; a speed with no direction turns clockwise</td>
</tr>
<tr>
<td>Feedrate column (mm/min)</td>
<td><code>Feedrate_mmdmin</code></td>
<td>the feedrate section</td>
</tr>
<tr>
<td>Step duration column (s)</td>
<td><code>StepDuration</code></td>
<td>the recorded-timing section</td>
</tr>
<tr>
<td>Actual time column</td>
<td><code>ActualTime</code></td>
<td>the recorded-timing section</td>
</tr>
<tr>
<td>Coolant column</td>
<td><code>Coolant</code></td>
<td>the coolant section</td>
</tr>
<tr>
<td>Line-begin C# script column</td>
<td><code>LineBeginCsScript</code></td>
<td>the script section, run before the row</td>
</tr>
<tr>
<td>Line-end C# script column</td>
<td><code>LineEndCsScript</code></td>
<td>the script section, run after the row</td>
</tr>
</tbody>
</table>
<p>Four things that table does not show on its own:</p>
<ul>
<li><strong>The cutter-location prefix is stored, serialized and editable, and no syntax in the shipped CSV
pipeline reads it.</strong> Columns under it are not consumed as coordinates; they survive into the
residual telemetry below.</li>
<li><strong>Naming a column consumes it.</strong> Each syntax removes the columns its tags name from the decoded
row, and whatever is left over is carried onto the step as recorded data — sensor channels, file
and line bookkeeping, anything else the file holds. So clearing a tag does more than stop the value
being used: it moves that column into the residual set.</li>
<li><strong>The duration cell is read as a time span rather than as a number of seconds</strong>, despite the
field's own <code>(s)</code>. A cell that does not parse falls back to the difference between this row's
actual time and the previous parseable one, and a resolved duration longer than one minute is
clamped to one minute, on the reasoning that a longer gap is spliced recordings rather than
machining time.</li>
<li><strong>An empty field is a real edit.</strong> The write applies every field the payload carries, and the panel
sends exactly the field that changed, so blanking a box clears that tag on the model rather than
leaving it alone.</li>
</ul>
<p>Each field commits on blur or on Enter — never while typing — and sends only itself. There is no
validation on either side of the wire: no trimming, no bounds, no uniqueness.</p>
<h2 id="cl-controller">CL Controller</h2>
<p>The node is the face of the project's resident NX-CL suit
(<a class="xref" href="../../api/Hi.MachiningProcs.MachiningProject.html#Hi_MachiningProcs_MachiningProject_ClsfRunnerSuit">ClsfRunnerSuit</a>), constructed the same way beside the brand
suit and the CSV suit, its runner a <a class="xref" href="../../api/Hi.NcParsers.SoftNcRunner.html">SoftNcRunner</a> assembled as the CLSF pipeline
by the factory <a class="xref" href="../../api/Hi.Numerical.ClsfParsers.NxClRunner.html">NxClRunner</a>. Its caption reads <em>&quot;Plays NX
cutter-location files (CLSF) — a mission Program File of CL kind or a script's <code>PlayClFile(&quot;…&quot;)</code>.&quot;</em></p>
<p>Everything on the panel is one <a class="xref" href="../../api/Hi.Numerical.ClsfParsers.ClsfRunnerConfig.html">ClsfRunnerConfig</a>, and every field on
it answers something a cutter-location file cannot say for itself.</p>
<p><strong>Rapid feedrate (assumed)</strong>, suffixed <code>mm/min</code>, and <strong>Rotary rapid feedrate (assumed)</strong>, suffixed
<code>deg/min</code>, default to 20000 and 36000. A CLSF carries no machine axes, so a <code>RAPID</code> move has nothing
to be timed against — but the two rates are not read on the same path, and the machining chain
decides which. On a pure-CL chain the CLSF pipeline's own motion semantic reads the linear rate
straight off this configuration and times every rapid from it; the rotary rate is never consulted.
On a machine-tool chain, where each CLSF block is re-expressed in machine coordinates and routed to
the motion semantics reused from the NC pipeline, the configuration doubles as the pipeline's
rapid-feedrate provider and answers axis-uniformly — every linear axis gets the first rate, every
rotary axis the second — and that is the only place the rotary rate is read.</p>
<p>Both fields carry a minimum of 1: a smaller value is refused inside the widget itself, which shows
<em>Must be ≥ 1</em> under the box and emits nothing, so no request is made and no toast appears. The
server's own positivity check sits behind that and is not reachable from this panel. A cleared or
non-finite entry is dropped by the panel before the request, which leaves the box showing what was
typed while the stored rate stands; selecting another node and returning restores the box.</p>
<p><strong>Prefer Tool House on LOAD/TOOL</strong> is a toggle, on by default, committing on the click. Its caption
sits below it permanently rather than as a field hint: <em>&quot;On: a LOAD/TOOL id already configured in the
Tool House keeps that tool (CLSF TLDATA geometry ignored). Off: TLDATA overwrites the tool-house
entry on every load.&quot;</em> That is what the code does — a tool change requesting an id the tool house
already holds is left alone while the toggle is on, and the file's own tool geometry rebuilds the
entry when it is off. Either way an id the house does not hold is built from the file's tool data,
and an id with neither is reported as a configuration error.</p>
<p><strong>Excluded record words</strong> is a chip field: a word typed and entered joins the list, and there is no
dropdown, because the option list is deliberately empty. Its preset list is <code>PAINT</code>, <code>TOOLNO</code>,
<code>LOADTL</code>, <code>TOOL PATH</code>, <code>TOOLPATH</code> and <code>END-OF-PATH</code>. A CLSF record that reaches the end of the
pipeline unhandled is otherwise reported as a validation warning naming the record word; a word on
this list is consumed silently instead, matched whole and without regard to case. Adding or removing
one chip writes the whole list, the server trims each word and drops the blank ones before replacing
the stored list, and the panel keeps what was typed — so a word entered with stray whitespace reads
differently on screen from what was stored, until the panel is remounted.</p>
<h2 id="layout">Layout</h2>
<ul>
<li>App Menu Bar
<ul>
<li><strong>Preference ▾</strong> Dropdown — fetches both runner snapshots as it opens, and only with a project
open
<ul>
<li><strong>CSV Controller</strong> CheckBox
<ul>
<li>Usage Caption — <em>&ldquo;This project plays CSV&rdquo;</em>, <em>&ldquo;Not used by this project&rdquo;</em>, or blank</li>
</ul>
</li>
<li><strong>CL Controller</strong> CheckBox
<ul>
<li>Usage Caption — the same three states, for CL</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><strong>General Setup</strong> Control Tree — the left dock of <code>/general-setup</code>
<ul>
<li><strong>General Setup</strong> Group Row — <code>equipment</code>
<ul>
<li><strong>Controller</strong> Node Row — the brand branch, built ahead of the two rows below</li>
<li><strong>CSV Controller</strong> Node Row — <code>equipment/controller-csv</code>; present only under the conditions
above, and pushed before the CL row when both are</li>
<li><strong>CL Controller</strong> Node Row — <code>equipment/controller-cl</code>; the last row the group can carry. Each
is a plain label with no icon, no checkbox and no children</li>
</ul>
</li>
</ul>
</li>
<li>Editor Row — the panel of whichever node is selected
<ul>
<li><strong>General Setup</strong> Group Panel — where a switched-off node's selection lands: the group's intro
caption over a bordered, separated list of its children, one clickable row each</li>
<li><strong>CSV Controller</strong> Panel
<ul>
<li>No-Project Body — <em>&quot;No project loaded.&quot;</em></li>
<li>No-Config Body — <em>&quot;No CSV column config on the CSV runner.&quot;</em></li>
<li>Editor Body
<ul>
<li>Intro Caption — the column-tags line, with <code>PlayCsvFile(&quot;…&quot;)</code> set in code</li>
<li>Tag Text Field, one per row, in this order: <strong>Machine coordinate prefix</strong> (hint <em>e.g. &ldquo;MC.&rdquo; →
MC.X / MC.Y / MC.Z</em>), <strong>Cutter location prefix</strong> (hint <em>e.g. &ldquo;CL.&rdquo; → CL.X / CL.Y / CL.Z</em>),
<strong>Tool id column</strong>, <strong>Spindle speed column (rpm)</strong>, <strong>Spindle direction column</strong>,
<strong>Feedrate column (mm/min)</strong>, <strong>Step duration column (s)</strong> (hint <em>Overrides feedrate-derived
timing.</em>), <strong>Actual time column</strong> (hint <em>Wall-clock instant of the row.</em>), <strong>Coolant column</strong>
(hint <em>Flood / Mist / Off or on/off.</em>), <strong>Line-begin C# script column</strong> (hint <em>Runs before the
row.</em>), <strong>Line-end C# script column</strong> (hint <em>Runs after the row.</em>)</li>
</ul>
</li>
</ul>
</li>
<li><strong>CL Controller</strong> Panel
<ul>
<li>No-Project Body — <em>&quot;No project loaded.&quot;</em></li>
<li>No-Config Body — <em>&quot;No CLSF config on the CL runner.&quot;</em></li>
<li>Editor Body
<ul>
<li>Intro Caption — the plays-CLSF line, with <code>PlayClFile(&quot;…&quot;)</code> set in code</li>
<li><strong>Rapid feedrate (assumed)</strong> Numeric Field — suffixed <code>mm/min</code>, minimum 1</li>
<li><strong>Rotary rapid feedrate (assumed)</strong> Numeric Field — suffixed <code>deg/min</code>, minimum 1</li>
<li><strong>Prefer Tool House on LOAD/TOOL</strong> Toggle</li>
<li>Policy Caption — the <em>On: … Off: …</em> explanation, always shown</li>
<li><strong>Excluded record words</strong> Chip Field — free-text entry with no dropdown list, hint <em>Record
words consumed silently as intentional skips (case-insensitive). Type + Enter to add.</em></li>
</ul>
</li>
</ul>
</li>
<li>Toast — negative, three seconds, the panel's context followed by the server's own message</li>
</ul>
</li>
</ul>
<h2 id="source-code-path">Source Code Path</h2>
<p>See <a class="xref" href="../index.html">HiNC App Anatomy</a> for git repository links.</p>
<h3 id="web-application">Web Application</h3>
<p>HiNC-2025-webservice (Quasar CLI SPA):</p>
<ul>
<li><code>wwwroot-src/src/components/controlTree/useControlTreeHost.ts</code> — the build rule that mints the two
nodes and where in the equipment group they sit, the checkbox watch that steps the selection off a
node losing its box before the rebuild, and the route-adoption guard that refuses an id the built
tree lacks.</li>
<li><code>wwwroot-src/src/components/controlTree/runnerSuitItemTypes.ts</code> — the two item types and the panels
they bind to; its own docblock names the usage evidence and the persisted selection as reveal
conditions, which the host's build rule does not.</li>
<li><code>wwwroot-src/src/components/controlTree/CsvRunnerPanel.vue</code> — the column-tag form: the two guards,
the field list with its labels and hints, the blur-and-Enter commit with its equality guard against
the fetched mirror, and the single-field payload.</li>
<li><code>wwwroot-src/src/components/controlTree/ClRunnerPanel.vue</code> — the CLSF form: the two rapid rates,
the cleared and non-finite values it drops before the request, the equality guard on each rate and
on the tool-house toggle, and the unguarded whole-list chip write.</li>
<li><code>wwwroot-src/src/composables/useViewPrefs.ts</code> — the device-local browser-storage record behind both
checkboxes: their default, their persistence, and the record they share with the tree's expansion
and last-selection memory.</li>
<li><code>wwwroot-src/src/components/AppMenuBar.vue</code> — the Preference dropdown's two checkboxes, and the
caption refresh that fetches both snapshots as the menu opens.</li>
<li><code>wwwroot-src/src/api/csvRunner.ts</code> and <code>wwwroot-src/src/api/clRunner.ts</code> — the two snapshot shapes,
their pre-fetch empty values, and the typed wrappers over each REST surface.</li>
<li><code>wwwroot-src/src/api/http.ts</code> — the plain-JSON read that inspects no envelope, beside the envelope
write that throws a <code>success: false</code> message.</li>
<li><code>wwwroot-src/src/components/widgets/NumericInput.vue</code> — the field behind the two rapid rates: commit
on blur or Enter, and the minimum that reports inline without emitting.</li>
<li><code>wwwroot-src/src/components/controlTree/PrimarySlavePanel.vue</code> — the editor row: the remount key
that refetches when the selection moves, and the select-an-item hint a refused deep link leaves
behind.</li>
<li><code>wwwroot-src/src/components/controlTree/GroupInfoPanel.vue</code> — the General Setup group's editor,
whose clickable child list gains and loses these two rows with the tree.</li>
<li><code>wwwroot-src/src/components/controlTree/itemTypes.ts</code> — the registry the two item types are spread
into, and the panel lookup the editor row resolves through.</li>
<li><code>wwwroot-src/src/router/treeRoutes.ts</code> — the id migration applied to a <code>?tree=</code> value before the
reveal test reads it, and the page roots a foreign id is redirected by.</li>
<li><code>wwwroot-src/src/pages/GeneralSetupPage.vue</code> — the route that creates the equipment-scoped tree host
and calls its initialization.</li>
<li><code>wwwroot-src/src/layouts/MainLayout.vue</code> — the project epoch that rebuilds the page when a project
loads, which is what lets a link opened against an empty application land afterwards.</li>
<li><code>wwwroot-src/src/i18n/en/tree.ts</code> — the two node labels, both panels' intros, empty lines, field
labels, hints and error contexts.</li>
<li><code>wwwroot-src/src/i18n/en/menu.ts</code> — the two checkbox labels and the two usage-caption strings.</li>
<li><code>wwwroot-src/src/i18n/en/common.ts</code> — the shared &ldquo;No project loaded.&rdquo; line both panels open with.</li>
<li><code>Mech/CsvRunnerController.cs</code> — the CSV suit's REST surface: the snapshot, the write that applies
only the fields the payload carries, and the success envelope a missing config is reported in.</li>
<li><code>Mech/ClRunnerController.cs</code> — the CL suit's REST surface: the same envelope, the positivity checks
on the two rates, and the trim-and-replace of the excluded-word list.</li>
<li><code>Mech/NcSuitUsage.cs</code> — the usage scan behind the two captions: the mission walk that reads through
a command's enable wrapper, the two script substrings, the extension detection for an Auto Program
File, and the CL-only chain test.</li>
</ul>
<h3 id="hiapi-engine">HiAPI Engine</h3>
<ul>
<li><code>HiNc/MachiningProcs/MachiningProject.cs</code> — the two resident suits as property-initialized members,
their load paths with the fall back to a fresh pipeline, and the migration of the older flat CSV
column element into the suit.</li>
<li><code>HiNc/MachiningProcs/LocalProjectService.cs</code> — the re-bind that wires both suits to the host
alongside the brand suit, and the chain walk that clears a generic axis configuration before
stamping the chain's axes onto it.</li>
<li><code>HiNc/MachiningProcs/SessionShell.cs</code> — the script verbs whose call text the caption's evidence
scan matches: the two play verbs, and the two CSV sensor-mapping verbs that end in the same
substring.</li>
<li><code>HiNc/SessionCommands/NcFileCommand.cs</code> — the Program File command whose kind the scan reads, and
its Auto default.</li>
<li><code>HiNc/SessionCommands/EnablingWrapper.cs</code> — the enable wrapper the scan walks through without
reading, which is why a switched-off command still counts as evidence.</li>
<li><code>HiMech/MachiningProcs/NcKind.cs</code> — the kind enum and the closed extension sets behind the Auto
detection.</li>
<li><code>HiMech/Numerical/CsvParsers/GeneralCsvRunner.cs</code> — the factory that assembles the suit's runner as
the CSV pipeline, and the place its column configuration sits in that pipeline.</li>
<li><code>HiMech/Numerical/CsvParsers/CsvRunnerConfig.cs</code> — the eleven tags, their serialization, and the
constants they default to.</li>
<li><code>HiMech/Mapping/MappingUtil.cs</code> — those constants.</li>
<li><code>HiMech/Numerical/CsvParsers/CsvSegmenter.cs</code> — the header row the tags are matched against, and
the quote-then-whitespace trim applied to each title.</li>
<li><code>HiMech/Numerical/CsvParsers/RowToSyntaxs/RowToMachineCoordinateSyntax.cs</code> — the six axis names the
machine-coordinate prefix is composed with, and the consumption of those columns whether or not
they resolved.</li>
<li><code>HiMech/Numerical/CsvParsers/CsvSemantics/CsvTimingUtil.cs</code> — the duration parse, the actual-time
fallback and the one-minute clamp.</li>
<li><code>HiMech/Numerical/CsvParsers/CsvSemantics/CsvActDataSemantic.cs</code> — the residual columns carried onto
the step, which is where a column no tag names ends up.</li>
<li><code>HiMech/Numerical/ClsfParsers/NxClRunner.cs</code> — the factory that assembles the CLSF pipeline, and
the configuration's place in it.</li>
<li><code>HiMech/Numerical/ClsfParsers/ClsfRunnerConfig.cs</code> — the four values, their defaults, and the
axis-uniform rapid-rate provider the machine-coordinate motion semantics read.</li>
<li><code>HiMech/Numerical/ClsfParsers/ClMotionValveSemantic.cs</code> — the router that sends a block carrying
machine coordinates to the semantics reused from the NC pipeline and every other block to the
pure-CL one, which is what decides whether the rotary rate is read at all.</li>
<li><code>HiMech/Numerical/ClsfParsers/ClMotionSemantic.cs</code> — the pure-CL motion semantic, timing a rapid
from the linear rate taken directly off the configuration.</li>
<li><code>HiMech/Numerical/ClsfParsers/ClsfRecordCleanupSyntax.cs</code> — the excluded-word match, and the
validation warning it replaces with a silent consume.</li>
<li><code>HiMech/Numerical/ClsfParsers/ClsfToolBuildSemantic.cs</code> — the tool-house policy: the entry that
wins, the file's tool data that builds a missing one, and the error when neither answers.</li>
<li><code>HiMech/Milling/ClMillingDevice.cs</code> — the chain type that is CL usage evidence on its own.</li>
</ul>
<h2 id="see-also">See Also</h2>
<ul>
<li><a class="xref" href="index.html">General Setup Page</a> — the page whose tree these two nodes are minted into, and the
equipment items they sit after</li>
<li><a class="xref" href="../shell/preference-menu.html">Preference Menu Dropdown</a> — the dropdown holding the two checkboxes and their usage captions,
and the other per-user settings beside them</li>
<li><a class="xref" href="controller/brand-matrix.html">Brand Matrix</a> — the other kind of missing node: which leaf the brand branch
grows on which brand, and the snapshot flag behind each one</li>
</ul>
</article>
<div class="contribution d-print-none">
</div>
<div class="next-article d-print-none border-top" id="nextArticle"></div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<span> Copyright © 2025 <a href='https://superhightech.com.tw'>Tech Coordinate</a>. All rights reserved. <a href='https://superhightech.com.tw'>超級高科技股份有限公司</a> © 2025 版權所有 </span>
</div>
</div>
</footer>
</body>
</html>