Workflow: Coloring Steps by Condition over the HTTP API
Replay Acceptance over the HTTP API ends with a run that played the whole mission and was accepted on evidence. This page sorts that run's steps into categories by conditions on their step properties — a color tree — and reports each category's share of the steps and of the machining time, over the HTTP API, for a script or an agent with no canvas to look at. It is written for an instance other people may be watching: §1 to §4 change neither the project nor the colors anyone sees; §5 adds the tree without overwriting one someone else put; and the one step that changes the colors on every screen, §6, is optional and puts them back at its end, unless someone else has changed the color index meanwhile.
Sign-in, the reply envelope and the other conventions every route here follows are
Driving the Web Service over HTTP. Every route, field and answer code
used below is in Step Color Trees over HTTP, and how a tree
sorts the steps and colors its leaves is Color Trees. The same
tree built in the browser is Step Colors, where each node is numbered as it is
added — Cut, the leaf a new tree starts with, as 1 — so the leaves' ids, and with them the automatic hues,
differ from the ones here. Every body below is JSON, sent
with Content-Type: application/json.
flowchart LR
Look["Look<br>keep the color index"]
Write["Write the tree"]
Check["Check"]
Preview["Preview<br>shares per leaf"]
Put["Put, add only"]
Show["Show it<br>only when asked"]
Back["Put the color<br>index back"]
Save["Save"]
Look --> Write --> Check --> Preview --> Put --> Save
Check -->|problems| Write
Preview -->|409, send again| Preview
Put -.->|on screen| Show --> Back --> Save
1. Look first, and keep the color index
Every request of this section reads and changes nothing. First the run:
GET /api/Execution/status
executionStatus is Finished. Keep the runId, the instanceId and the resetCount beside it:
§4 reads them again, to know that the steps it counted are still this run's. Running or Paused is
a play changing the steps under every request below — wait for it to end, and never stop or reset a
run you cannot prove is yours. NoProject means no project is open.
GET /api/execution/cl-strip/range
count is the number of positions on the step strip, above 0; it is <count> below. Then the
project's trees, the keys a tree can read, and the color index:
GET /api/execution/step-color-trees?lang=en
The answer is { success, generation, physicsShown, inspectingKey, trees, registeredAtRun, keyOptions },
or success: false with code NoProjectLoaded when no project is open.
inspectingKeyis the color index: the step property the Color Index Time Chart plots and the 3D view colors the tool path and the cut faces by, a project setting every connected screen follows. Keep it exactly as it is,nullincluded: §4 checks it, and §6 reads it again before it sets another.GET /api/execution/strip-chart-item-configwithout a key answers the same value as itsinspectingKey.currentKeyofGET /api/execution/step-propertiesis not it: while the physics keys are hidden and the color index is one of them, that field names the key shown in its place.keyOptionsare the step properties a term can name, each{ key, name, unit, unitLabel, kind, isPhysics, source }. The keys of §2 are among them:IsRapidandIsTouchedwithkindbool, and, whilephysicsShownis true, the three ratios withkindquantityandisPhysicstrue.physicsShownfalse — Show Physics Options off, or no physics licence — leaves the physics keys out ofkeyOptions, andcheckand thePUTthen warn about each one the tree names; the tree reads them all the same. Leave the preference as it is: it is the instance's, shared by every user.treesandregisteredAtRunare the trees the project defines and the ones a mission script registered for the session. A tree there that already asks the question needs no copy when it is one ofregisteredAtRunor itsstateisregistered, the trees a preview by key reads: preview it by its key (§4) and report from that.
Choose the tree's key before going on: one that no entry of trees, registeredAtRun or keyOptions
has, and that is not inspectingKey itself — a removed tree leaves its key as the color index until
someone sets another, and a tree added under that key would recolor every screen at once. A built-in
step property's key, or one under MC., is refused (400 StepColorTreeKeyTaken); a project step
variable's answers 409 in §5; a project tree under a key a script registered takes that key over for
the session. This page uses LoadCheck.
2. Write the tree
A tree is a list of nodes tried from the top: the first leaf whose condition holds takes the step and
gives it its color, and a leaf without a condition, "when": null, takes every step that reaches it.
The categories here are four:
| Leaf | Takes a step when |
|---|---|
| Overload | any of the yielding stress ratio, the max spindle torque ratio and the max spindle power ratio is above 1 |
| Rapid | it is a rapid move: IsRapid is yes |
| Air | it touches nothing: IsTouched is no |
| Cut | otherwise; the chart draws its max spindle power ratio inside its lane |
{"key": "LoadCheck", "name": "Load check", "nodes": [
{"kind": "leaf", "name": "Overload", "hue": 0, "when": {"join": "any", "terms": [
{"key": "YieldingStressRatio", "op": "gt", "threshold": 1},
{"key": "MaxSpindleTorqueRatio", "op": "gt", "threshold": 1},
{"key": "MaxSpindlePowerRatio", "op": "gt", "threshold": 1}]}},
{"kind": "leaf", "name": "Rapid", "when": {"join": "all", "terms": [{"key": "IsRapid", "op": "eq", "threshold": 1}]}},
{"kind": "leaf", "name": "Air", "when": {"join": "all", "terms": [{"key": "IsTouched", "op": "eq", "threshold": 0}]}},
{"kind": "leaf", "name": "Cut", "when": null, "valueKey": "MaxSpindlePowerRatio"}]}
- The order is the meaning. An overload is an Overload on a rapid move too, a rapid move is a Rapid whether it touches anything or not, and Air takes the feed moves that touch nothing.
- The ids are the server's. A tree being added leaves out
idandnextId; the server numbers the nodes in the order written — Overload 1, Rapid 2, Air 3, Cut 4 — and a leaf's id is the tree's value on each of its steps. - Yes and no read as 1 and 0, so
eqwith1asks for yes and with0for no. - No value fails every comparison. The three ratios have a value only where the physics ran, and the two spindle ratios only where the project's spindle capability gives limits at the step's speed: a step without them is no Overload and goes on to the leaves below.
- The threshold
1— each ratio's 100 % — is this example's choice, not a limit HiNC sets. The thermal yield ratio is left out: under a toolmaker's recommended cutting data it usually reads above 100 % (Thermal Plastic Deformation of Cutting Edge), so a leaf on it would mark ordinary cuts. hueis a leaf's hue in degrees, picked here for Overload alone; a leaf without one gets an automatic hue from its id.valueKeychanges no color: it names the value the Color Index Time Chart draws inside the leaf's lane.
3. Check it
POST /api/execution/step-color-trees/check
Content-Type: application/json
{"key": "LoadCheck", "name": "Load check", "nodes": [
{"kind": "leaf", "name": "Overload", "hue": 0, "when": {"join": "any", "terms": [
{"key": "YieldingStressRatio", "op": "gt", "threshold": 1},
{"key": "MaxSpindleTorqueRatio", "op": "gt", "threshold": 1},
{"key": "MaxSpindlePowerRatio", "op": "gt", "threshold": 1}]}},
{"kind": "leaf", "name": "Rapid", "when": {"join": "all", "terms": [{"key": "IsRapid", "op": "eq", "threshold": 1}]}},
{"kind": "leaf", "name": "Air", "when": {"join": "all", "terms": [{"key": "IsTouched", "op": "eq", "threshold": 0}]}},
{"kind": "leaf", "name": "Cut", "when": null, "valueKey": "MaxSpindlePowerRatio"}]}
The answer is { success, problems, messages, referencedKeys }. Accept the tree when:
problemsis empty. A problem is{ code, path, refuses },pathits place in the body, such asnodes[0].when.terms[2]: one withrefuses: truekeeps the tree from registering — fix it and check again; one withrefuses: falseis registered as it is, with a warning.messagesis empty, or holds three rows whoseidisStepColorTree-Term--PhysicsHidden, one per ratio, whilephysicsShownis false. A rowStepColorTree-Term--KeyUnresolvednames a key no step property has: a misspelt key reads as no value on every step.referencedKeysis["YieldingStressRatio", "MaxSpindleTorqueRatio", "MaxSpindlePowerRatio", "IsRapid", "IsTouched"], each a key ofkeyOptions— the three ratios excepted whilephysicsShownis false.
A body that is not a tree as written answers 400 with a code and args: path, the place in the
body, and for some codes a reason; Answers lists
every code. check changes nothing.
4. Preview it over the whole run, and read the shares
POST /api/execution/step-color-trees/preview
Content-Type: application/json
{"tree": {"key": "LoadCheck", "name": "Load check", "nodes": [
{"kind": "leaf", "name": "Overload", "hue": 0, "when": {"join": "any", "terms": [
{"key": "YieldingStressRatio", "op": "gt", "threshold": 1},
{"key": "MaxSpindleTorqueRatio", "op": "gt", "threshold": 1},
{"key": "MaxSpindlePowerRatio", "op": "gt", "threshold": 1}]}},
{"kind": "leaf", "name": "Rapid", "when": {"join": "all", "terms": [{"key": "IsRapid", "op": "eq", "threshold": 1}]}},
{"kind": "leaf", "name": "Air", "when": {"join": "all", "terms": [{"key": "IsTouched", "op": "eq", "threshold": 0}]}},
{"kind": "leaf", "name": "Cut", "when": null, "valueKey": "MaxSpindlePowerRatio"}]},
"range": "all"}
The preview reads the played steps themselves and writes nothing. Its histogram is the answer to the
question:
leaveslists every leaf in tree order,{ id, name, steps, seconds, share, firstStepIndex }: the steps the leaf took; their simulated time summed, in seconds;share, that time's part of the time of every step scanned; and the first of them, −1 for none. A leaf's share of the steps is itsstepsoverscannedSteps.noValue,{ steps, seconds, share }, is the steps no leaf took.
selectedStep explains the step selected on the instance, or is null; it is not needed yet. Accept the
shares on evidence:
| Check | Where | Pass |
|---|---|---|
| The whole run was read | histogram |
range is all, begin 0 and end <count>; scannedSteps is <count>, less any position that holds no step (a step whose building failed, reported as Step-Task--Fault); skippedPositions is 0 |
| Every step is in a category | histogram |
the leaves' steps and noValue.steps add up to scannedSteps; with an otherwise leaf last, noValue.steps equals faultedSteps, the steps whose read failed, and is 0 |
| The ratios were computed | selectedStep of the request below |
Cut's first step reads numbers for the three ratios |
| The color index untouched | inspectingKey of the answer |
the key kept in §1 |
| Still the run of §1 | GET /api/Execution/status |
runId, instanceId and resetCount as kept in §1 |
To see why a step is where it is, name it — here Cut's first step, the firstStepIndex of the leaf
whose name is Cut (−1 when Cut took no step: name another leaf's first step). Find Cut by its
name, not by a number: a tree previewed by its key keeps the ids it was built with, and the same
tree built by the steps of Step Colors has Cut 1, Overload 2, Rapid 3
and Air 4:
POST /api/execution/step-color-trees/preview
Content-Type: application/json
{"tree": {"key": "LoadCheck", "name": "Load check", "nodes": [
{"kind": "leaf", "name": "Overload", "hue": 0, "when": {"join": "any", "terms": [
{"key": "YieldingStressRatio", "op": "gt", "threshold": 1},
{"key": "MaxSpindleTorqueRatio", "op": "gt", "threshold": 1},
{"key": "MaxSpindlePowerRatio", "op": "gt", "threshold": 1}]}},
{"kind": "leaf", "name": "Rapid", "when": {"join": "all", "terms": [{"key": "IsRapid", "op": "eq", "threshold": 1}]}},
{"kind": "leaf", "name": "Air", "when": {"join": "all", "terms": [{"key": "IsTouched", "op": "eq", "threshold": 0}]}},
{"kind": "leaf", "name": "Cut", "when": null, "valueKey": "MaxSpindlePowerRatio"}]},
"range": "all", "stepIndex": <Cut's firstStepIndex>}
selectedStep is { stepIndex, leafId, leafName, leafValue, values, trace, error }. On Cut's first step
leafName is Cut and leafId Cut's id in the histogram; trace lists the nodes tried in order, each { id, name, kind, held }
— Overload, Rapid and Air with held: false, Cut last with held: true; values holds the step's value
under each key the tree reads, { key, value }, IsRapid 0 and IsTouched 1 among them; leafValue is
its max spindle power ratio; error is null unless a read failed. The three ratios must be numbers
there. A value that is not a number travels as the string "NaN": all three "NaN" on a cutting step
means the play computed no physics there, and the two spindle ratios alone that the project's spindle
capability gives no limits at the step's speed — either way no step without them can be an Overload,
and Overload's share says nothing about the load of those steps. Named with Overload's
firstStepIndex instead, the same request shows which ratio is above 1.
A 409 StepColorTreePreviewSuperseded is a preview stopped before its end: by another preview — one
runs at a time on the instance, whoever sends it, a Preview in the browser included — or by a change
to the steps under it, such as a reset, a recompute of the step physics, a key registered or set as the
color index, or values written onto the steps. Send it again; a 409 that keeps coming back is someone
else at work on the instance, so leave time between the tries. It works the other way too: a preview
sent here stops one running in someone's browser, whose panel then says that its preview was stopped,
so send a preview when its answer is needed, never in a loop. A stepIndex the strip holds no step at
answers 400: StepColorTreeNoStep, or StepColorTreeStepNotBuiltYet for the index a play would build
next.
The shares are the report, and getting them changed neither the project nor any screen. Report
each leaf's name, steps, seconds and share, the noValue row when it is not empty, and the evidence
above. An Overload share is a reading of the simulation before it is a finding about the program:
check it against what the project assumes before calling it a risk
(Simulation Report).
Go on only when the tree is to stay with the project, to be shown on screen, or to give the step file a
column.
5. Add it to the project, as an add only
PUT /api/execution/step-color-trees/LoadCheck
Content-Type: application/json
If-None-Match: *
{"key": "LoadCheck", "name": "Load check", "nodes": [
{"kind": "leaf", "name": "Overload", "hue": 0, "when": {"join": "any", "terms": [
{"key": "YieldingStressRatio", "op": "gt", "threshold": 1},
{"key": "MaxSpindleTorqueRatio", "op": "gt", "threshold": 1},
{"key": "MaxSpindlePowerRatio", "op": "gt", "threshold": 1}]}},
{"kind": "leaf", "name": "Rapid", "when": {"join": "all", "terms": [{"key": "IsRapid", "op": "eq", "threshold": 1}]}},
{"kind": "leaf", "name": "Air", "when": {"join": "all", "terms": [{"key": "IsTouched", "op": "eq", "threshold": 0}]}},
{"kind": "leaf", "name": "Cut", "when": null, "valueKey": "MaxSpindlePowerRatio"}]}
A 200, { success, item, appearanceOnly, renamedFrom, messages, generation }, is the tree added:
item.state is registered and item.problems empty; item.tree is the tree numbered, ids 1 to 4 and
nextId 5; item.leaves gives each leaf as { id, lane, name, hue, hueAuto, color, valueKey }, color
the #RRGGBB the charts and the 3D view paint its steps; appearanceOnly is false and renamedFrom
null. messages repeats what check said, followed by what the project's other step definitions
report. The tree is in the open project's memory until §7 saves it. Adding it registers the project's
step definitions again, which stops a preview running at that moment (409), and leaves every screen's
colors as they are: those follow the color index alone.
- 412
StepColorTreeKeyRepeated: the project has a tree under the key — another caller's, or one from an earlier try of this run whose answer was lost — and nothing changed. Read it withGET /api/execution/step-color-trees/LoadCheckand compare itsitem.treewith §2's node by node — names, hues, conditions, value keys; the ids are the server's. The same tree: preview it by its key,{"key": "LoadCheck", "range": "all"}, and go on. Another tree: choose another key and put again. Never send thePUTagain withoutIf-None-Match: without it the request replaces the tree someone else put. - 409
StepColorTreeKeyRepeated: the project has a step variable under the key, as themessagesays. Choose another key. - 400: the key refused, as §1 describes, or the body, as §3 does.
6. Only when it must be on screen: set it as the color index, then put the old one back
This is the one step that changes what other people see. The color index is a project setting: setting it repaints the Color Index Time Chart and the colors of the tool path and the cut faces on every screen connected to the instance — the chart in four lanes named Overload, Rapid, Air and Cut from the top, the run in the leaves' colors — and a save keeps it. Do it only when the tree is to be shown, and keep it short.
Read the color index once more, GET /api/execution/step-color-trees?lang=en, and keep its
inspectingKey, null included, as the key to put back — not §1's: a key another user has set since
§1 is theirs. Then make the tree the color index:
POST /api/execution/inspecting-key
Content-Type: application/json
{"inspectingKey": "LoadCheck"}
The answer is { success, currentKey, messages }, with currentKey LoadCheck. The field is
inspectingKey and nothing else in the body is read: {"key": "LoadCheck"} clears the color index and
still answers success: true, with currentKey: null.
The host then fills each step's cached value of the color index in the background. Read the chart over
the whole run, again after a moment, until pending is false:
GET /api/execution/strip-chart?aspect=Individual&inspectingKey=LoadCheck&xValueCategory=IndexByStep&widthHint=1&dispBegin=0&dispEnd=<count>
items[0].colorTree.leafTotalsholds one entry per leaf,{ lane, id, steps, seconds }, over the steps the answer covers, andnoValueTotals,{ steps, seconds }, the steps in no leaf. Matched byid— the list is in tree order, so never index it by lane — each leaf'sstepsequal those of §4'shistogram, or of §5's preview by key when the tree was already in the project, and itssecondsagree with them.dispBeginanddispEndmake the answer cover the run, not the window on display;widthHint=1keeps it to two points, while the totals still count every step.itemsempty withpending: truemeansLoadCheckis not the color index: another user has set another one since. Stop there, and leave theirs.
Then put the color index back, unless someone else has changed it meanwhile. Read it again:
GET /api/execution/step-color-trees?lang=en
While inspectingKey is still LoadCheck, post the key kept before LoadCheck was set — the JSON
null, unquoted, when there was none — and accept on a currentKey equal to it:
POST /api/execution/inspecting-key
Content-Type: application/json
{"inspectingKey": "<the key kept before LoadCheck was set>"}
Any other inspectingKey is another user's choice since §6 began: leave it. Read
GET /api/Execution/status once more as §4 does: the same runId, instanceId and resetCount say
the totals counted the run of §1.
7. Save the project, and give the step file a column
POST /api/Project/save
A 200, { "success": true, "message": "Project saved successfully" }, is the project file written with
the tree in it; a 409 is another project file operation in progress, so save again after it, and a 400
gives the reason in message, no project open among them. The save writes the open project as it
stands: the tree, every other edit made to it since it was last saved, other users' included, and the
color index as it is at that moment — which is why §6 puts the color index back first. A tree that is
never saved is lost when the project is reloaded or another one is opened.
Per-step data comes from a step file, the CSV that a Post-Execution command's Step Files Output
writes during a play
(Writing out what the run produced).
It has a column under every step property's key, so the tree's column, LoadCheck, holds each step's
leaf id; item.leaves of GET /api/execution/step-color-trees/LoadCheck turns an id into its leaf's
name. Only a file written while the tree was in the project has the column, and the run of §1 played
before the tree was added. To have one, play the mission again as
Replay Acceptance plays it — a reset and a start, which everyone on the instance
sees — with a Post-Execution below the programs, the command enabled
(PUT /api/Mission/commands/{path}/enabled with true as the body) and its step files on
(PUT /api/Mission/commands/{path}/postexecution/enable-write-step-files with true), {path} the
command's entry path as
Project Construction
writes it. Enabling the command runs every output switched on under it, not only the step files: read
its entry in GET /api/Mission/list-command/entries first — the enable… fields of its command say
which — and keep its isEnabled and command.enableWriteStepFiles. Both PUTs change the mission in
memory after the save above, so once the replay has written the files, put both back as they were, or
the next save, anyone's, keeps them. Each file is named by its StepFile-Create--Start row
(Replay Acceptance §4). A file holds one
program, and the writer opens it afresh each time the play returns to that program from another, so a
program that calls another keeps only its rows after the last call, and counts taken from the files
then fall short of §4's.
See Also
- Replay Acceptance over the HTTP API — producing and accepting the run these steps come from, and the replay a step file's column needs
- Step Color Trees over HTTP — every route, field and answer used here, the shape of a tree, and the shared color index
- Driving the Web Service over HTTP — sign-in, the reply envelope, one service with one project
- Color Trees — how a tree sorts the steps and colors its leaves
- Step Colors — the same tree built and previewed in the browser
- Simulation Report — where the shares go, and the checks a load reading needs before it is called a risk