Skip to content

Live value procedures

Three procedures read and write the canonical string values of parameters:

  • parameter.readValues returns one complete batch { results }.
  • parameter.readValuesStream returns progressive result and ping events. The shared live coordinator that Setup and dashboards use calls it.
  • parameter.writeValues writes values.

All three take parameter ids only, never Modbus addresses. The server resolves each parameter’s workspace and checks access. The input and output types are exported by @overvis/hmi-shared/parameter. Recorded history is in the readings procedures. Endpoint connection status and raw Modbus traffic have their own subscriptions (endpoint.watchStatus, endpoint.traffic); see the API reference. Dashboards call these procedures through the live-value hooks.

Requests for the same parameter can share one device read, and a successful read taken a moment earlier can answer another request. This applies equally to polling and to explicit reads. Writes and relevant configuration changes discard such readings. A shared result keeps the original acquiredAt, so a repeated delivery never makes an older measurement look newly read.

Each device read is stored once in the parameter’s history, including reads that live views request; a shared result adds nothing, while separate reads with unchanged values each add a sample. A reading reaches history shortly after the live response, and aggregated reports wait for their time bucket to close. A live response does not guarantee that the reading has already been stored: a service interruption can lose recent samples.

{
paramIds: uuid[]; // 1–10_000
}
{
results: Record<
uuid,
| {
status: "ok";
kind?: "observation";
acquiredAt?: string; // ISO acquisition time; unchanged when a reading is reused
value: LocalizedString; // plain string ≤1024, or locale map when repr substitutes
rawHex: string; // required; lowercase hex of pre-decode source bytes, no 0x, ≤8192 chars
numberValue?: number;
boolValue?: boolean;
}
| {
status: "error";
error: ParameterRuntimeError; // discriminated by code + reason; message is debug only
}
>;
}

Results are per parameter. One failed id does not fail the call.

numberValue and boolValue are present for numeric and Boolean types. value is a LocalizedString: a plain canonical string, or a locale map when an int or bool repr substitutes a display label. Display resolves the map in the order active locale, en, first key.

rawHex is the exact source blob before decode: the Modbus payload, the const storage bytes, or the packed calc result, without multipliers or byte-relation transforms. Setup’s Hex display mode shows it.

Same input as readValues. It is a streaming mutation with no single { results } output. It yields:

| { type: "result"; paramId: uuid; result: /* same per-id shape as readValues.results[id] */ }
| { type: "ping" } // idle keepalive (~10s) while waiting on device I/O

Aborting a request ends its stream without adding timeout results for unfinished parameters. When the request reaches its 30-second timeout, the remaining parameters receive per-parameter timeout errors.

{
items: Array<
// 1–10_000; each item is exactly one of:
| { paramId: uuid; value: string /* ≤1024 */ }
| { paramId: uuid; rawHex: string /* lowercase [0-9a-f]*, ≤8192 */ }
>;
}
  • value writes go through encode and writeValidation. Int and bool parameters with repr labels also accept the labels, in any locale. The string forms per value type are in write strings.
  • rawHex writes replace the exact span, without encode and without engineering writeValidation. The length must exactly match the parameter’s device span (its Modbus address span) or the current const blob. For an empty const blob, a fixed-width value type must match its canonical device width. An odd length, bad hex, or a length mismatch fails with encode_error or bad_request. The bytes must still decode with the parameter’s valueType; otherwise the write fails with decode_error before anything changes, so the acknowledgement always has a decoded value. Coil tables turn each byte into 00 or ff. A bit-field bool replaces the full span, not a single bit.

The results record keeps per-parameter errors. A successful item has status: "ok", kind: "write-acknowledgement", sourceKind: "modbus-tcp" | "const", and an ISO writtenAt timestamp, the time the source write completed. value is decoded from the written bytes and rawHex is their hexadecimal form; numberValue and boolValue remain optional typed projections. These fields describe the write, not a new observation. For Modbus, the result acknowledges the write with the bytes sent; the procedure does not read the register afterward. For const sources, the result describes the bytes saved to const storage.

value can differ from the typed input when transforms or repr labels normalize it, and a read afterwards can show something else without the write having failed: a device can clamp a value, a command register can clear itself after it runs, and some devices report a command’s effect in another register. Choose read-back targets from the device’s command semantics. Acknowledged bytes never replace the last reading and never enter history or live reports as measured samples.

SourceWritable when
constallowWrite: true
calcNever
modbus-tcpWritable table and writeFunction is not none

A write to a parameter that is not writable fails with not_writable. Writes also fail for disabled parameters, unknown ids, encode and validation errors, and device or endpoint problems.

There is no multi-parameter transaction and no all-or-nothing flag. Each item succeeds or fails on its own; the server keeps every write it applied. Writing three setpoints may yield two ok and one endpoint_disconnected. A client applies the successful values and shows the failed IDs with their errors; rolling back the successes would undo real device writes.

Per-parameter errors carry error.code and an optional reason:

CodeMeaning
bad_requestMalformed request or missing write value
workspace_disabledThe parameter’s workspace is suspended
param_not_foundUnknown parameter id, or a parameter the caller cannot reach
param_disabledThe parameter has disabledSince set; checked before encode
not_writableCalc, const without allowWrite, read-only Modbus table, or none
unsupported_value_typePacking not implemented for live I/O (float16, IEEE decimal*)
decode_errorBytes to value failed, or the device response was corrupt
encode_errorValue to bytes failed, or writeValidation refused the value
formula_errorA calc or transform formula failed
cycle_detectedCalc dependency cycle
depth_exceededCalc graph too deep
atomic_unsatisfiableA Modbus atomic span does not fit one PDU
sparse_write_unsupportedThe write function cannot write this address list
endpoint_not_foundEndpoint missing from setup
endpoint_disconnectedEndpoint disabled or not connected
modbus_exceptionDevice exception PDU (params: exceptionCode, functionCode, address, …)
timeoutConnection or response timeout
connector_rejectedThe cloud refused the device request: busy, oversized, or endpoint not ready
internal_errorUnexpected failure

An API key scoped to another workspace gets param_not_found for the parameters of this one.

These usually come with encode_error:

reasonMeaning
write_value_below_minBelow the configured min (params.value, params.min)
write_value_exceeds_maxAbove the configured max
write_invalid_number / write_invalid_integer / write_invalid_bigintThe value does not parse
write_value_not_allowedNot in the allow-list
write_value_too_short / write_value_too_longString length (params.minLength / maxLength)
reasonMeaning
endpoint_settings_invalidThe endpoint’s stored settings cannot be parsed
endpoint_disabledThe endpoint was disabled on purpose
endpoint_status_unavailableNo current status of the endpoint is available
endpoint_connect_failed / endpoint_connection_lostThe network connection could not be opened, or was lost
device_response_timeoutThe endpoint path exists, but the unit (params.unitId) did not answer in time
request_queue_timeout / request_queue_fullThe cloud’s request queue for this endpoint was full or timed out
request_too_largeThe requested Modbus work exceeds the per-request limit
service_not_readyThe live-reading service is temporarily unavailable
parameter_source_invalidThe stored parameter source is malformed
parameter_value_type_invalidThe stored parameter value type is malformed
request_service_timeoutThe API wait deadline expired; device reachability is unknown
device_response_invalidThe device returned a malformed or mismatched Modbus response
value_unavailableThe reading matched readUnavailableValue (decode_error)
timestamp_unavailableThe timestamp read as zero with zeroIsUnavailable (decode_error)

request_service_timeout says nothing about whether the endpoint connected or the unit answered. The Device not responding diagnosis rests only on device_response_timeout, or on a gateway’s Modbus exception 10 or 11, which say that the unit behind the gateway did not answer.

Setup and dashboards show value_unavailable and timestamp_unavailable as Reading unavailable, a neutral status rather than a configuration warning. It replaces any reading shown before, until a valid value arrives. Such readings are not recorded in history.

The runtime error schema validates each combination of code, reason, and required params. Modbus exceptions carry exceptionCode, functionCode, address, quantity, unitId, and table. The English message and params.detail are for logs; the UI builds localized messages from code, reason, and params.

Authentication and access failures abort the whole call with a procedure error and no results. Per-id runtime codes appear inside a successful response, in results[id].error.

FailureHow it appears
Not signed in, or a bad API keytRPC or HTTP error; no results
workspace_no_access / workspace_not_operatorProcedure error; writing needs the operator role or higher
Unknown id in a batchresults[id].status === "error" with param_not_found
Device timeoutPer-id timeout or endpoint_disconnected