Gateway tag engineering
Open Tags in the workspace's left navigation to create memory values, OPC UA bindings, saved device/source-point tags, gateway expressions and read-only references. The separate Models workspace groups those values into reusable models and equipment, with versions, parameters and a location hierarchy; its fields expand to ordinary tags. Both workspaces are reached from the left navigation, not from Gateway Settings. Expressions execute on the gateway, independently of browser sessions. Configuration, import and export operations require Configuration capability or administrator access in an engineering session; imports also require the normal CSRF token and are audited. Follow the UNS model walkthrough for the complete source-to-faceplate workflow.
Expression tags
An expression declares named inputs mapped to concrete existing tag paths. For example, a Double tag can use count * 60 / seconds, with inputs count and seconds pointing to two memory or OPC UA tags. Another Boolean expression can depend on that expression using rate >= 0 && rate <= 25.
Supported syntax includes numbers, JSON quoted strings, true, false, named inputs, parentheses, arithmetic + - * / %, comparisons < <= > >= == !=, Boolean && || !, and unary + -. There are no function calls, scripts, assignments, network operations or dynamic property access. String concatenation is not supported. Equality requires matching scalar types; arithmetic requires numeric operands and Boolean operators require Boolean operands. The declared output type is checked without coercing a fraction to an integer or a number to a Boolean.
Numbers use IEEE-754 doubles. Integer inputs and literals outside ±9,007,199,254,740,991 are rejected rather than rounded; memory, source and reference tags retain their existing original types. Each expression is limited to 2,048 characters, 256 tokens, 64 nesting levels and 32 named inputs. A gateway supports at most 10,000 configured tags, including expanded UDT members, with at most 64 expression/reference tags in a dependency chain. Self-references, cycles, missing input paths and deletion of a referenced tag are rejected before saving. The checks include disabled definitions, so enabling them cannot introduce a previously hidden cycle.
The publishing interval is also the expression evaluation interval, from 100 to 60,000 ms, on a 100 ms scheduler. This is not a real-time guarantee. Dependency ordering applies when expressions are due in the same scheduler pass; a slower dependency retains its prior result until its own next evaluation. Every declared input must have good quality, even when a Boolean branch would short-circuit. A bad input propagates its quality and a null result, division by zero produces Bad_ExpressionError, and invalid operand or output types produce Bad_TypeMismatch. Disabled expressions produce Bad_Disabled.
Derived timestamps use the newest contributing source timestamp. Re-evaluation alone does not advance them. Constants retain their timestamp until their result or quality changes. These timestamps describe source data, not evaluation duration or receipt time. The Tag editor exposes the result and quality; all tag consumers receive the same path, data type, value, quality and timestamp contract.
Reviewed bulk import and export
Choose Tags → Import / export. Export configured tags downloads the complete sparkstudio-tags.json package containing configured definitions, hierarchy, types, pinned instances and authored memory defaults. Live memory values are checkpointed separately in tag-values.json; they are not added to the configuration export. The envelope contains no connector credentials or connection definitions. Treat authored defaults as application data when storing or sharing exports.
Import previews each path as add, update or unchanged, and the total tag count after applying. It merges matching paths and retains existing resources not in the import. Deletion requires explicit removal arrays in a supported model package. A package can refer to another tag defined later in that same package. All rows, connection references, input paths, reference targets, type parameters, composition and the complete resulting dependency graph are validated together.
The review's Reference targets after apply table shows the resulting reference paths and resolved targets, including unchanged aliases. Read permission on an alias exposes the target value even when the caller cannot read the target source path directly. Configuration administrators must deliberately review those exposures before applying; source-path restrictions alone do not protect values published through readable references.
Apply revalidates under the store lock, checks the preview against both the current tag configuration and connection configuration, and atomically replaces tags.json once. No partial rows are saved when validation or conflict checks fail. A concurrent configuration edit, connection change or edited file invalidates the preview; preview again before applying. Runtime memory writes do not change the configuration revision. Their checkpoint values remain active for unchanged expanded definitions; changing a definition invalidates its old checkpoint and uses its authored default. Changing a gateway tag affects every project that uses it immediately; project publication does not create a private copy of gateway tag configuration.
There is one current tag-model schema, with format: "sparkstudio.tags" and internal identifier version: 3. Older tag envelopes and flat arrays are not accepted. The resulting gateway model must fit the 10,000 expanded-tag ceiling. Only tag preview/apply requests permit bodies up to 32 MiB; other ordinary API routes retain their 1 MiB limit. Fields must match the chosen source. Connections and saved source points must already exist and match the referenced IDs; references need existing tags of exactly the same data type.
Tag storage uses that same current schema and does not automatically migrate older files. An incompatible stored file is rejected without being rewritten. Use matching gateway binaries and a complete backup for recovery; see gateway recovery.
Endpoints under /api or a project API scope are GET /tag-engineering/export, POST /tag-engineering/preview with the envelope, and POST /tag-engineering/apply with { package, revision, previewToken }. The preview token is an optimistic concurrency fingerprint, not an authorization credential. The authenticated apply endpoint performs all validation again.
Workshop: production rate
examples/tag-engineering.json is independently authored synthetic source for a separate Tag engineering workshop project. It is setup-required because four gateway tags are deliberately excluded from .sparkproj packages. The example creates no external connection and does not command equipment. It requires the expression-tag build, an engineering administrator for setup, the bundled Python worker for the save action, and an operator with Operate permission for that project.
- On a disposable development gateway, provide a protected local JSON credential file with
usernameandpassword, or use an existing disposable test-account file with anadminentry. Set its path inSPARKSTUDIO_ADMIN_AUTH_FILE. Never add this file to a repository or release. - Run
node tools/load-tag-engineering-example.mjs http://127.0.0.1:5091. Add--publishonly when you want to publish the newly created project immediately. The loader refuses an existing project name or any of the reserved[default]TagWorkshoppaths. Tag import is atomic; creating the project is a separate operation. If project creation fails, the four newly created tags remain available for inspection. - Open the new project in Designer, inspect the expressions in Tags, publish the project and open its operator link. Initial readings are 12 counts in 30 seconds: the rate is 24 per minute and Within limit is true.
- Save 20 counts in 30 seconds. The rate becomes 40 and Within limit becomes false. The button writes only synthetic memory values; both derived tags are read-only.
- Save zero seconds. The derived values become unavailable with
Bad_ExpressionError; restore 30 seconds to recover. Disable Count in Tags and save to propagateBad_Disabled; re-enable it to recover. - Export the configured tags. Choose that file in Import / export and preview it. Change Count's definition in another engineering session after preview, then try Apply; the server refuses the stale review. Preview again to proceed. A runtime write to Count alone does not invalidate the configuration preview.
- Try changing Rate to depend on WithinLimit while WithinLimit depends on Rate. The editor refuses the cycle and retains the prior definitions.
You may export the project as .sparkproj and distribute it separately from a reviewed tag JSON package. Import the gateway tags before publishing its screens on another gateway. The project package does not carry users, grants or gateway tags.
Current scope and verification
Tag engineering has bounded expressions, read-only references, dependency validation, source quality/timestamp propagation and reviewed atomic bulk import/export. See tag models for provider lifecycle, scan groups and type composition, or the UNS workshop for two CSV-created CNC instances and reusable faceplates. The configuration ceiling is distinct from throughput: historian configuration still permits 5,000 recorded tags and 2,000 alarms. See load testing for measured workloads and limitations.
Run node tools/test-tag-engineering.mjs --model for isolated filesystem, graph, parser, live engine and concurrency tests. Run node tools/test-tag-engineering.mjs with SPARKSTUDIO_TEST_AUTH_FILE pointing to an isolated authenticated port 5091 test-account fixture to check HTTP authorization, audience separation, CSRF, import conflicts and live expression results. Neither test targets the installed gateway on port 5090.
Live values and write durability
Runtime tag definitions are cached per configuration generation. Memory writes
update the shared in-memory value set immediately and checkpoint tag-values.json
in a coalesced batch about once per second. tags.json retains definitions and
configured defaults. Clean shutdown and scheduled configuration backups flush the
value checkpoint. Abrupt power loss can lose approximately the latest second of
memory updates; use a transactional database for records that need stronger
commit guarantees. Multi-path memory writes do not rewrite tag configuration once
per path.
Synthetic [default]Line/* demonstration values are disabled by default. Enable
SparkStudio:EnableDemoTags explicitly only for a development/demo gateway.
Line and Setpoints are ordinary folder names: configured memory, expression
and OPC UA tags may use them, including paths shown by the sample project. An
explicit definition always takes precedence over optional demo data, even when
that definition is disabled or unavailable. Configured memory values use normal
datatype validation and persistence; the demo's temporary target-speed behavior
applies only when that exact tag has no configured definition.
Operator event streams send an initial snapshot, then bounded tags-delta
upserts/removals and heartbeats. Each authenticated sign-in is limited to 32 tag
streams; overflow causes a fresh snapshot rather than silent permanent drift.