Archived
534 lines
32 KiB
HTML
534 lines
32 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>Program Reading | HiAPI-C# 2025 </title>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="title" content="Program Reading | 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 "{query}"">
|
||
<meta name="loc:searchNoResults" content="No results for "{query}"">
|
||
<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-ControllerProgramReading">
|
||
<h1 id="program-reading">Program Reading</h1>
|
||
|
||
<p>Program Reading is the pair of Machine / Controller leaves that change how the runner <em>reads</em> a
|
||
program rather than how the machine moves: which block-skip layers are active, and where a
|
||
subprogram call goes looking for its file. Both live on the General Setup page at <code>/general-setup</code>,
|
||
under the Control-Tree ids <code>equipment/controller/machine/block-skip</code> and
|
||
<code>equipment/controller/machine/subprograms</code>. The pair is also unevenly branded — every shipped brand
|
||
preset carries the subprogram-folder config, and one of the five carries no block-skip config at
|
||
all.</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="the-asymmetry">The Asymmetry</h2>
|
||
<p>Both nodes are grown behind a plain presence probe over the runner's proxy-resolved dependency
|
||
list: <code>hasBlockSkip</code> is set when the list holds any
|
||
<a class="xref" href="../../../../api/Hi.NcParsers.Dependencys.IBlockSkipConfig.html">IBlockSkipConfig</a>, <code>hasSubprogramFolders</code> when it holds a
|
||
<a class="xref" href="../../../../api/Hi.NcParsers.Dependencys.Generic.SubProgramFolderConfig.html">SubProgramFolderConfig</a>. Neither probe inspects a value.</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Brand preset</th>
|
||
<th>Block-skip config</th>
|
||
<th>Subprogram-folder config</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Fanuc</td>
|
||
<td>yes</td>
|
||
<td>yes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Siemens</td>
|
||
<td>yes</td>
|
||
<td>yes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Syntec</td>
|
||
<td>yes</td>
|
||
<td>yes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Mazak</td>
|
||
<td>yes</td>
|
||
<td>yes</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Heidenhain</td>
|
||
<td><strong>no</strong></td>
|
||
<td>yes</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><a class="xref" href="../../../../api/Hi.NcParsers.Dependencys.Generic.GenericBlockSkipConfig.html">GenericBlockSkipConfig</a> is the <strong>only</strong> implementer of the
|
||
block-skip interface anywhere in the engine, and the Heidenhain preset's pipeline list is the one of
|
||
the five that does not carry it. That single omission is what makes Block Skip / Delete the one node
|
||
in the whole Controller branch that exists on four brands and not the fifth; every other gate on
|
||
this plane is satisfied either by all five presets or by a Siemens-only table. Which flag each row
|
||
answers to is <a class="xref" href="../brand-matrix.html">Brand Matrix</a>.</p>
|
||
<p>The config is not the only thing missing there. The block-skip switches gate a parsing syntax,
|
||
<a class="xref" href="../../../../api/Hi.NcParsers.ParsingSyntaxs.BlockSkipSyntax.html">BlockSkipSyntax</a>, and that syntax appears in the Fanuc, Siemens,
|
||
Syntec and Mazak syntax lists and in no other — the Heidenhain list carries no block-delete parser,
|
||
so on that preset the nine switches would have nothing to gate.</p>
|
||
<p>The subprogram-folder config runs the other way: all five presets carry one, and five call
|
||
statements across three brand families read the same two values. The node's own vocabulary is
|
||
Fanuc's, because the storage is, but the setting is not Fanuc-only.</p>
|
||
<h2 id="block-skip--delete">Block Skip / Delete</h2>
|
||
<p>The panel is a caption over nine checkboxes and nothing else. The caption reads <em>"Enabled layers
|
||
skip their <code>/n</code>-prefixed blocks (<code>/</code> alone = layer 1)."</em>, the first box is labelled <em>"Layer 1
|
||
(bare /)"</em> and the rest <em>“Layer 2”</em> through <em>“Layer 9”</em>.</p>
|
||
<h3 id="what-a-layer-does-to-a-block">What a layer does to a block</h3>
|
||
<p><a class="xref" href="../../../../api/Hi.NcParsers.ParsingSyntaxs.BlockSkipSyntax.html">BlockSkipSyntax</a> matches a leading <code>/</code> optionally followed by a
|
||
single digit <code>1</code>–<code>9</code>; a bare slash is layer 1. It then always writes a
|
||
<a class="xref" href="../../../../api/Hi.NcParsers.Keywords.BlockSkip.html">BlockSkip</a> section recording the symbol and the layer, and always
|
||
consumes the prefix out of the block's unparsed text — so the <code>/</code> itself never survives as residue
|
||
for the downstream unrecognized-text check, whatever the switches say.</p>
|
||
<p>What the switch decides is the block's <strong>body</strong>:</p>
|
||
<ul>
|
||
<li><strong>Layer on</strong> — the remaining text is moved into
|
||
<a class="xref" href="../../../../api/Hi.NcParsers.Keywords.BlockSkip.html#Hi_NcParsers_Keywords_BlockSkip_Body">Body</a> and the unparsed text is cleared. Every downstream
|
||
parsing syntax then sees nothing, so the block emits no NC act, and the run records
|
||
<code>BlockSkip--Skipped</code> at message severity for that block.</li>
|
||
<li><strong>Layer off, or no config at all</strong> — the body stays null and the rest of the block parses exactly
|
||
as an unprefixed one would. A runner with no block-skip config therefore simulates the whole
|
||
program, which is the safe reading of an unknown machine setting.</li>
|
||
</ul>
|
||
<p>Ordering matters for one thing and is fixed in each brand's list: the comment and NC-embedded
|
||
script syntaxes run <strong>before</strong> the block-skip syntax, so a comment on a skipped block — and any
|
||
script embedded in it — still takes effect while the motion beside it does not.</p>
|
||
<h3 id="one-value-seven-spellings-of-the-same-range">One value, seven spellings of the same range</h3>
|
||
<p>Layers 1 through 9 are the whole range, and no shared constant carries it. The bound is written out
|
||
separately in the parsing syntax's regular expression, in the config's XML reader and again in its
|
||
CSV setter, in its per-layer mutator guard, in the read endpoint that enumerates the layers, in the
|
||
write endpoint that loops over them, and in the panel's checkbox repeat. A tenth layer is therefore
|
||
seven edits, not one, and a partial change would be silent — a switch the panel offered but the
|
||
config refused to store would simply never take.</p>
|
||
<h3 id="what-a-fully-cleared-set-does-not-survive">What a fully cleared set does not survive</h3>
|
||
<p>A freshly applied preset has layer 1 on and the other eight off. The stored form is a
|
||
comma-separated list of the enabled layers, and an empty set serializes as an empty element. The
|
||
reader treats a blank list and a missing element identically — both mean <em>layer 1 only</em> — so
|
||
clearing every box and then reloading the project brings layer 1 back on. Every other combination
|
||
round-trips exactly.</p>
|
||
<h3 id="the-write">The write</h3>
|
||
<p>Each box commits on the click, and the request is the <strong>whole</strong> enabled set rather than the one
|
||
layer that changed: the panel sorts its set and sends it, and the endpoint walks 1 through 9 setting
|
||
each layer to whether the payload names it. A failed write restores the previous set and raises a
|
||
toast; the shared rules behind that shape are
|
||
<a class="xref" href="../editing-contract.html">Editing Contract</a>.</p>
|
||
<p>On the brand that carries no config, the read answers <em>not present</em> with an empty layer list and any
|
||
write is answered unsuccessfully with <em>“No IBlockSkipConfig on the active runner”</em> — but the node is
|
||
not built there, so neither answer is reachable from the tree.</p>
|
||
<h2 id="subprogram-folders">Subprogram Folders</h2>
|
||
<p>Two plain text fields, labelled <em>"Internal folder (M98)"</em> and <em>"External folder (M198)"</em>, hinted
|
||
<em>“Relative to the host NC file's folder; empty = that folder itself”</em> and <em>“Fanuc external-storage
|
||
calls; empty = fall back to the internal folder”</em>. They write
|
||
<a class="xref" href="../../../../api/Hi.NcParsers.Dependencys.Generic.SubProgramFolderConfig.html#Hi_NcParsers_Dependencys_Generic_SubProgramFolderConfig_InternalFolder">InternalFolder</a> and
|
||
<a class="xref" href="../../../../api/Hi.NcParsers.Dependencys.Generic.SubProgramFolderConfig.html#Hi_NcParsers_Dependencys_Generic_SubProgramFolderConfig_ExternalFolder">ExternalFolder</a>; an empty or
|
||
whitespace-only box is stored as null rather than as an empty string.</p>
|
||
<h3 id="which-call-statements-read-these-two-values">Which call statements read these two values</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Preset</th>
|
||
<th>Call statement</th>
|
||
<th>Field it reads</th>
|
||
<th>File-name chain, first match wins</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Fanuc, Mazak, Syntec</td>
|
||
<td><code>M98 P_ L_</code></td>
|
||
<td>Internal</td>
|
||
<td><code>O{P:D4}.NC</code>, <code>O{P}.NC</code>, <code>O{P:D4}</code>, <code>O{P}</code>, <code>{P:D4}.NC</code>, <code>{P}.NC</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Fanuc, Mazak, Syntec</td>
|
||
<td><code>M198 P_</code></td>
|
||
<td>External, falling back to Internal when it is null</td>
|
||
<td>the same chain</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Fanuc</td>
|
||
<td><code>G65</code> / <code>G66</code> macro call</td>
|
||
<td>Internal</td>
|
||
<td>the same chain</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Siemens</td>
|
||
<td>name call (<code>L9810</code>, a named cycle)</td>
|
||
<td>Internal</td>
|
||
<td><code>{name}.SPF</code>, <code>{name}.MPF</code>, <code>{name}</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Heidenhain</td>
|
||
<td><code>CALL PGM name</code></td>
|
||
<td>Internal</td>
|
||
<td><code>{name}.h</code>, <code>{name}.H</code>, <code>{name}</code></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Two consequences follow from the table, and both are invisible from the field labels.</p>
|
||
<p><strong>The External folder is inert on two brands.</strong> Only the Fanuc-family inliner,
|
||
<a class="xref" href="../../../../api/Hi.NcParsers.EvaluationSyntaxs.SubProgramCallSyntax.html">SubProgramCallSyntax</a>, ever reads it — the Siemens and
|
||
Heidenhain call syntaxes look up their callee through the Internal folder alone. The field is
|
||
offered on every brand because the storage is brand-neutral, and it is honoured on the three that
|
||
have an <code>M198</code>.</p>
|
||
<p><strong>The Internal folder is read by more than the M98 label says.</strong> On the Fanuc preset it also anchors
|
||
both Custom Macro B lookups — <a class="xref" href="../../../../api/Hi.NcParsers.EvaluationSyntaxs.Fanuc.FanucMacroCallSyntax.html">FanucMacroCallSyntax</a> for
|
||
the <code>G65</code> one-shot call and <a class="xref" href="../../../../api/Hi.NcParsers.EvaluationSyntaxs.Fanuc.FanucModalMacroSyntax.html">FanucModalMacroSyntax</a> for
|
||
the <code>G66</code> modal — and on Siemens and Heidenhain it is the <em>only</em> subprogram root there is. Emptying
|
||
it to fix an M98 path therefore moves the macro and named-call lookups with it.</p>
|
||
<p>Each brand also brings its own file-name chain, and the chains are per-syntax properties rather than
|
||
one shared list — the Fanuc chain is
|
||
<a class="xref" href="../../../../api/Hi.NcParsers.EvaluationSyntaxs.MacroFileResolver.html#Hi_NcParsers_EvaluationSyntaxs_MacroFileResolver_FilenamePatterns">FilenamePatterns</a>, a static array every
|
||
Fanuc-family caller shares, while
|
||
<a class="xref" href="../../../../api/Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensSubProgramCallSyntax.html#Hi_NcParsers_EvaluationSyntaxs_Siemens_SiemensSubProgramCallSyntax_FilePatterns">FilePatterns</a> and
|
||
<a class="xref" href="../../../../api/Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainSubProgramCallSyntax.html#Hi_NcParsers_EvaluationSyntaxs_Heidenhain_HeidenhainSubProgramCallSyntax_FilePatterns">FilePatterns</a> are
|
||
instance properties of their own call syntaxes and are re-writable from the runner file. Case
|
||
matching is delegated to the host file system throughout, which is why the Heidenhain chain carries
|
||
both <code>.h</code> and <code>.H</code>.</p>
|
||
<h3 id="where-a-relative-folder-is-anchored">Where a relative folder is anchored</h3>
|
||
<p>The resolver takes the folder as written. An absolute path is used unchanged. A relative path — and
|
||
an empty one, which means <em>the root itself</em> — is combined with the base directory supplied by
|
||
<a class="xref" href="../../../../api/Hi.NcParsers.Dependencys.SystemWired.ProjectFolderDependency.html">ProjectFolderDependency</a>, and the machining session wires
|
||
that dependency to the <strong>project's</strong> own root before each play.</p>
|
||
<p>So the anchor is the project folder, not the folder the host NC file happens to sit in. A program
|
||
played from a subfolder of the project resolves <code>NC</code> against the project root, not against its own
|
||
neighbour of that name. The field's hint says otherwise, and so does the API summary on the two
|
||
config properties the panel writes; the resolver is what runs.</p>
|
||
<p>Two further conditions end the lookup before any pattern is tried: a relative folder with no base
|
||
directory resolves to nothing, and so does a folder that does not exist as a directory.</p>
|
||
<h3 id="a-missing-file-is-an-error-on-one-family-and-a-warning-on-the-other">A missing file is an error on one family and a warning on the other</h3>
|
||
<p>The same empty result is reported at two different severities, and the split follows the call
|
||
statement rather than the setting.</p>
|
||
<ul>
|
||
<li><strong>Fanuc, Mazak, Syntec</strong> — an unresolved <code>M98</code> / <code>M198</code> raises <code>SubProgramCall--FileNotFound</code> at
|
||
error severity, quoting the folder that was searched, and the call is consumed.</li>
|
||
<li><strong>Siemens, Heidenhain</strong> — an unresolved call raises <code>SiemensCall--Skipped</code> or
|
||
<code>HeidenhainCall--Skipped</code> at warning severity and is consumed with no motion effect. That is
|
||
deliberate: the common unresolved callee on those controls is an OEM or measuring cycle whose
|
||
definition file ships with the machine and never travels with the program, so a hard error would
|
||
fire on ordinary, correct programs.</li>
|
||
</ul>
|
||
<p>A resolved call is inlined: the callee is segmented through the runner's own segmenter and its
|
||
blocks are prepended into the program ahead of the host block, each stamped with a record naming the
|
||
call it came from. <code>M98</code> with an <code>L</code> count above one inlines the same file that many times in
|
||
series, each repetition its own segmentation pass.</p>
|
||
<h3 id="the-nesting-ceiling-and-where-there-is-none">The nesting ceiling, and where there is none</h3>
|
||
<p>A self- or mutually-recursive callee re-captures its own call statement inside every inlined body,
|
||
so a call path needs a rail of its own — no loop watchdog covers it. <strong>That rail is declared twice,
|
||
independently, and is missing on the third path.</strong></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Preset</th>
|
||
<th>Ceiling</th>
|
||
<th>Where it is declared</th>
|
||
<th>Exceeded</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Siemens</td>
|
||
<td>32 frames</td>
|
||
<td><a class="xref" href="../../../../api/Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensSubProgramCallSyntax.html#Hi_NcParsers_EvaluationSyntaxs_Siemens_SiemensSubProgramCallSyntax_DefaultMaxCallDepth">DefaultMaxCallDepth</a></td>
|
||
<td><code>SiemensCall--DepthLimitExceeded</code>, consumed as a safe skip</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Heidenhain</td>
|
||
<td>32 frames</td>
|
||
<td><a class="xref" href="../../../../api/Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainSubProgramCallSyntax.html#Hi_NcParsers_EvaluationSyntaxs_Heidenhain_HeidenhainSubProgramCallSyntax_DefaultMaxCallDepth">DefaultMaxCallDepth</a></td>
|
||
<td><code>HeidenhainCall--DepthLimitExceeded</code>, consumed as a safe skip</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Fanuc, Mazak, Syntec</td>
|
||
<td>none</td>
|
||
<td>—</td>
|
||
<td>—</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>The two constants are separate <code>const int</code> declarations on separate classes that happen to hold the
|
||
same number, each surfaced as its own writable <code>MaxCallDepth</code> property and each serialized into the
|
||
runner file as its own element. Raising one raises nothing else. Both compare against the depth of
|
||
the call stack already stamped on the host block, so the count is frames entered, not files listed.</p>
|
||
<p>On the Fanuc-family inliner and on both Custom Macro B calls there is no depth comparison at all.
|
||
None of them reads the host block's frame count before inlining, so none carries the recursion rail
|
||
the Siemens and Heidenhain syntaxes declare. The depth itself is recorded either way — every inlined
|
||
block is stamped with a pushed call-stack frame that the matching return statement pops — so what is
|
||
missing is the comparison, not the count.</p>
|
||
<p>The Heidenhain call syntax carries a second, unrelated ceiling for its section-repeat form:
|
||
<a class="xref" href="../../../../api/Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainSubProgramCallSyntax.html#Hi_NcParsers_EvaluationSyntaxs_Heidenhain_HeidenhainSubProgramCallSyntax_MaxRepetitions">MaxRepetitions</a> caps
|
||
a <code>REP</code> literal at 65534, since the repeat re-scans the file once per repetition.</p>
|
||
<h3 id="what-an-empty-internal-folder-does-not-survive">What an empty Internal folder does not survive</h3>
|
||
<p>The config's default internal folder is <code>NC</code> — the layout where the main program sits beside an
|
||
<code>NC/</code> directory of subprograms — and that default is applied by the property itself, before the XML
|
||
reader runs. The writer omits an element for a null folder, and the reader keeps whatever the
|
||
property already holds when the element is absent. Clearing the <strong>Internal folder</strong> box therefore
|
||
stores a null, writes no element, and reads back as <code>NC</code> the next time the project is opened.</p>
|
||
<p>The <strong>External folder</strong> box has no such default and round-trips cleanly: cleared, it stores null,
|
||
writes no element, and reads back null — which is the state the field's own hint describes, falling
|
||
back to the internal folder.</p>
|
||
<h2 id="editing-and-storage">Editing and Storage</h2>
|
||
<p>Both panels open with the branch's two empty layers — the shared <em>"No NC runner — load a project
|
||
first."</em> line first, then the panel's own read reporting <em>"No block-skip config on the active
|
||
runner."</em> or <em>"No subprogram-folder config on the active runner."</em> The first layer is a live guard
|
||
against the snapshot emptying under a panel that is already mounted, which is what closing the
|
||
project does. The second is unreachable by navigating: the node's gate and the panel's read probe
|
||
the same dependency on the same resolved list, so the leaf exists only where the read is about to
|
||
succeed.</p>
|
||
<p>Their commit shapes differ, and both are recorded in
|
||
<a class="xref" href="../editing-contract.html">Editing Contract</a>: the block-skip boxes commit on the click
|
||
and roll back on failure, while the two folder fields commit <strong>as a pair</strong> on blur or Enter of
|
||
either one, compared against a saved snapshot of both rather than a per-field captured value — so
|
||
editing one folder writes both, and a failure restores both.</p>
|
||
<p>Both configs are plain runner-owned entries rather than proxies, so their values serialize with the
|
||
runner and follow it. Installing a controller file replaces them outright, and a brand apply assigns
|
||
a whole fresh preset, so <strong>an applied brand change returns both to that preset's defaults</strong> — layer 1
|
||
alone, and the <code>NC</code> internal folder with no external one. Selecting the brand already in force is not
|
||
a route to that reset: the apply stays disabled until the selection differs from the runner's own
|
||
brand. Which half of a project each value on this plane lands in is
|
||
<a class="xref" href="index.html">Machine and Controller Plane</a>.</p>
|
||
<h2 id="layout">Layout</h2>
|
||
<ul>
|
||
<li><strong>General Setup</strong> Control Tree — the left dock of <code>/general-setup</code>
|
||
<ul>
|
||
<li><strong>Controller</strong> Node Row
|
||
<ul>
|
||
<li><strong>Machine / Controller</strong> Group Row
|
||
<ul>
|
||
<li><strong>Block Skip / Delete</strong> Node Row — <code>equipment/controller/machine/block-skip</code>, grown while
|
||
the snapshot reports a block-skip config</li>
|
||
<li><strong>Subprogram Folders</strong> Node Row — <code>equipment/controller/machine/subprograms</code>, grown while it
|
||
reports a subprogram-folder config</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li>Editor Row — <strong>Block Skip / Delete</strong> Panel
|
||
<ul>
|
||
<li>No-Runner Line — <em>"No NC runner — load a project first."</em>, the branch's shared empty state</li>
|
||
<li>No-Config Line — <em>"No block-skip config on the active runner."</em></li>
|
||
<li>Description Caption — <em>"Enabled layers skip their <code>/n</code>-prefixed blocks (<code>/</code> alone = layer 1)."</em></li>
|
||
<li>Layer CheckBox Column — nine dense boxes in one column
|
||
<ul>
|
||
<li><strong>Layer 1 (bare /)</strong> CheckBox</li>
|
||
<li><strong>Layer 2</strong> … <strong>Layer 9</strong> CheckBoxes</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li>Editor Row — <strong>Subprogram Folders</strong> Panel
|
||
<ul>
|
||
<li>No-Runner Line — the same shared empty state</li>
|
||
<li>No-Config Line — <em>"No subprogram-folder config on the active runner."</em></li>
|
||
<li><strong>Internal folder (M98)</strong> Field — outlined and dense, hinted <em>“Relative to the host NC file's
|
||
folder; empty = that folder itself”</em> — a hint the resolver contradicts, the anchor being the
|
||
project root</li>
|
||
<li><strong>External folder (M198)</strong> Field — outlined and dense, hinted <em>“Fanuc external-storage calls;
|
||
empty = fall back to the internal folder”</em></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<p>Every label above is a translated role string rather than a type name, so a locale change rewrites
|
||
what is read without touching an id. Both panels mount against one node and take nothing from it:
|
||
each serves a single tree id, so neither reads a role off the node's path.</p>
|
||
<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/SoftNcBlockSkipPanel.vue</code> — the block-skip panel: the two
|
||
empty layers, the caption with its two code slots, the nine boxes and their layer-one label, and
|
||
the whole-set write with its rollback.</li>
|
||
<li><code>wwwroot-src/src/components/controlTree/SoftNcSubprogramPanel.vue</code> — the folder panel: the two
|
||
outlined fields, the blur and Enter bindings on both, the saved-snapshot guard that skips a
|
||
redundant write, and the paired rollback.</li>
|
||
<li><code>wwwroot-src/src/components/controlTree/SoftNcEmptyState.vue</code> — the shared no-runner line both
|
||
panels open with.</li>
|
||
<li><code>wwwroot-src/src/components/controlTree/softNcItemTypes.ts</code> — the two node ids, their labels and
|
||
label keys, the snapshot flag each is pushed behind, and the item types that bind them to their
|
||
panels.</li>
|
||
<li><code>wwwroot-src/src/api/softNcRunner.ts</code> — the two readers and their coercions, the layer-array
|
||
writer, the paired folder writer, and the snapshot fields the gates read.</li>
|
||
<li><code>wwwroot-src/src/api/http.ts</code> — the envelope reader that turns an unsuccessful body into the error
|
||
a panel's toast quotes.</li>
|
||
<li><code>wwwroot-src/src/composables/useSoftNcRunner.ts</code> — the shared snapshot both first empty layers
|
||
read, and its once-per-session install.</li>
|
||
<li><code>wwwroot-src/src/i18n/en/softNc.ts</code> — the two node labels, the block-skip caption and layer
|
||
labels, the four folder strings, the two empty-state lines and the error contexts.</li>
|
||
<li><code>Mech/SoftNcRunnerController.cs</code> — the REST surface: the two presence probes on the snapshot, the
|
||
block-skip read that enumerates the nine layers and the write that sets each one, the folder read
|
||
that substitutes an empty string for a null and the write that substitutes a null for a blank, the
|
||
brand switch whose remark names both of these among the runner-owned values it resets, and the
|
||
shared helper that answers a missing dependency with an unsuccessful body rather than an error
|
||
status.</li>
|
||
</ul>
|
||
<h3 id="hiapi-engine">HiAPI Engine</h3>
|
||
<ul>
|
||
<li><code>HiMech/NcParsers/Dependencys/IBlockSkipConfig.cs</code> — the block-skip contract: the per-layer query
|
||
and mutator, and the stated safe default when the dependency is absent.</li>
|
||
<li><code>HiMech/NcParsers/Dependencys/Generic/GenericBlockSkipConfig.cs</code> — the only implementer: the
|
||
layer-one default, the comma-separated stored form, the range filter repeated in its reader and
|
||
its setter, and the blank-equals-absent rule behind the cleared-set round trip.</li>
|
||
<li><code>HiMech/NcParsers/ParsingSyntaxs/BlockSkipSyntax.cs</code> — the prefix parser: the layer regular
|
||
expression, the always-recorded section, the body move that silences a block, and the message the
|
||
skip reports.</li>
|
||
<li><code>HiMech/NcParsers/Keywords/BlockSkip.cs</code> — the recorded section: symbol, layer, and the body that
|
||
is null exactly when the skip did not take effect.</li>
|
||
<li><code>HiMech/NcParsers/Dependencys/Generic/SubProgramFolderConfig.cs</code> — the two folders, the <code>NC</code>
|
||
default applied by the property itself, the null fallbacks, and the writer that omits an element
|
||
for a null.</li>
|
||
<li><code>HiMech/NcParsers/EvaluationSyntaxs/SubProgramCallSyntax.cs</code> — the Fanuc-family inliner: the
|
||
internal-versus-external choice, the repetition loop, the file-not-found error, and the absence of
|
||
any call-depth comparison.</li>
|
||
<li><code>HiMech/NcParsers/EvaluationSyntaxs/MacroFileResolver.cs</code> — the shared resolver: the Fanuc file
|
||
name chain, the absolute-versus-relative anchoring, and the directory-exists precondition.</li>
|
||
<li><code>HiMech/NcParsers/EvaluationSyntaxs/Fanuc/FanucMacroCallSyntax.cs</code>,
|
||
<code>HiMech/NcParsers/EvaluationSyntaxs/Fanuc/FanucModalMacroSyntax.cs</code> — the other two Fanuc readers
|
||
of the internal folder: the <code>G65</code> one-shot macro call, and the <code>G66</code> modal that resolves the same
|
||
file again on every motion block it fires on.</li>
|
||
<li><code>HiMech/NcParsers/EvaluationSyntaxs/Siemens/SiemensSubProgramCallSyntax.cs</code> — the name-call
|
||
inliner: its own file-pattern chain, its own depth constant and property, and the safe-skip that
|
||
answers an unresolved OEM cycle.</li>
|
||
<li><code>HiMech/NcParsers/EvaluationSyntaxs/Heidenhain/HeidenhainSubProgramCallSyntax.cs</code> — the klartext
|
||
call inliner: the <code>CALL PGM</code> lookup through the same internal folder, the second depth constant,
|
||
and the separate repeat ceiling.</li>
|
||
<li><code>HiMech/NcParsers/Keywords/CallStack.cs</code>,
|
||
<code>HiMech/NcParsers/EvaluationSyntaxs/SubProgramReturnSyntax.cs</code> — the frame each inliner stamps on
|
||
an inlined block, and the <code>M99</code> return that pops it.</li>
|
||
<li><code>HiMech/NcParsers/NcDiagnosticProgress.cs</code> — the category and severity behind each diagnostic id
|
||
named above.</li>
|
||
<li><code>HiMech/NcParsers/Dependencys/SystemWired/ProjectFolderDependency.cs</code> — the base directory a
|
||
relative folder is anchored against, and the host-wired provider behind it.</li>
|
||
<li><code>HiMech/MachiningProcs/MachiningSession.cs</code> — where that provider is wired to the project root
|
||
before a play.</li>
|
||
<li><code>HiMech/NcParsers/SoftNcRunner.cs</code> — the five brand presets, and which of them carries each of
|
||
these two dependencies.</li>
|
||
<li><code>HiMech/NcParsers/Syntaxs/FanucSyntaxUtil.cs</code>,
|
||
<code>HiMech/NcParsers/Syntaxs/SiemensSyntaxUtil.cs</code>,
|
||
<code>HiMech/NcParsers/Syntaxs/SyntecSyntaxUtil.cs</code>,
|
||
<code>HiMech/NcParsers/Syntaxs/MazakSyntaxUtil.cs</code>,
|
||
<code>HiMech/NcParsers/Syntaxs/HeidenhainSyntaxUtil.cs</code> — the four lists that carry the block-skip
|
||
parser and the one that does not, and which call syntax each preset runs.</li>
|
||
</ul>
|
||
<h2 id="see-also">See Also</h2>
|
||
<ul>
|
||
<li><a class="xref" href="index.html">Machine and Controller Plane</a> — the plane these two leaves sit on, and the storage split that
|
||
decides which of its values a brand apply resets and which it leaves alone</li>
|
||
<li><a class="xref" href="../brand-matrix.html">Brand Matrix</a> — the two flags that grow these nodes, what each one probes,
|
||
and the brand sets they produce</li>
|
||
<li><a class="xref" href="../editing-contract.html">Editing Contract</a> — the commit, rollback and empty-state rules these panels
|
||
share with the branch, and the paired-field write recorded as one of its exceptions</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>
|