docs/chore: flag uns-loader README stale + add historian SQL reference; gitignore .claude tooling + local VPN notes
This commit is contained in:
@@ -6,3 +6,9 @@ bin/
|
||||
obj/
|
||||
[Aa]rtifacts/
|
||||
*.user
|
||||
|
||||
# Claude Code tooling / agent worktrees (local-only)
|
||||
.claude/
|
||||
|
||||
# Local ops/infra notes — internal access details, never publish
|
||||
zimmer-vpn-tunnel.md
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
# AVEVA Historian — SQL Reference: Tag Value Recording & Tag Registration
|
||||
|
||||
**Scope:** Writing tag values and creating new tags in AVEVA Historian (formerly Wonderware Historian) directly through SQL Server, against the `INSQL` OLE DB provider / `Runtime` database. Applies to **2020** and **2023 R2** (history-block / binary storage).
|
||||
|
||||
**Connection model:** Connect to the Historian's SQL Server instance (e.g. `Microsoft.Data.SqlClient`). The time-series tables are *extension tables* — they don't physically exist in SQL Server; the `INSQL` provider routes reads/writes into the on-disk history blocks. No Framework SDK / HCAL required for this path.
|
||||
|
||||
> **Out of scope:** Alarm/event recording. In high-speed mode the alarm/event store is fed **only** by the Application Server alarm provider — there is no supported SQL `INSERT` for alarms/events. Model process outcomes (pass/fail/cancel) as the tags below, or raise real alarms via an AppServer attribute. See the "Alarms/events" note at the end.
|
||||
|
||||
---
|
||||
|
||||
## 1. Recording tag VALUES via SQL
|
||||
|
||||
Two different tables depending on tag type. **This is the most common trap.**
|
||||
|
||||
### 1a. Analog & discrete tags → `History` table (numeric `Value`)
|
||||
|
||||
```sql
|
||||
INSERT INSQL.Runtime.dbo.History (DateTime, TagName, Value, QualityDetail, wwVersion)
|
||||
VALUES ('2026-06-18 10:00:00.000', 'LeakTest_Rate', 0.42, 0, 'Latest');
|
||||
```
|
||||
|
||||
- `Value` is a **float** (analog real value, or 0/1 for discrete).
|
||||
- Four-part naming: `INSQL.Runtime.dbo.History`.
|
||||
|
||||
### 1b. String tags → `StringHistory` table (string `Value`)
|
||||
|
||||
```sql
|
||||
INSERT INSQL.Runtime.dbo.StringHistory (DateTime, TagName, Value, QualityDetail, wwVersion)
|
||||
VALUES ('2026-06-18 10:00:00.000', 'LeakTest_Result', 'PASS', 0, 'Latest');
|
||||
```
|
||||
|
||||
- Use `StringHistory` + `Value`, **not** `History` + `vValue` for strings.
|
||||
- Inserting a string into `History.vValue` fails on 2023 R2 with
|
||||
`Msg 8114 ... Error converting data type nvarchar to (null)`.
|
||||
|
||||
### Column notes
|
||||
|
||||
| Column | Meaning |
|
||||
|---|---|
|
||||
| `DateTime` | Timestamp of the value (local server time unless using a UTC column). |
|
||||
| `TagName` | Must already exist (see Section 2 to create it). |
|
||||
| `Value` | Float in `History`; string in `StringHistory`. |
|
||||
| `QualityDetail` | `0` = good. (OPC-style alternative: `OPCQuality`, where `192` = good. Confirm which your queries expect.) |
|
||||
| `wwVersion` | `'Latest'` or `'Original'` — see below. |
|
||||
|
||||
### `wwVersion` / data versioning
|
||||
|
||||
- `'Latest'` — writes a **revision** that wins on retrieval.
|
||||
- `'Original'` — as-acquired value; never destroyed, still readable with `wwVersion = 'Original'`.
|
||||
- An "update" is really a new revision layered on top, not an overwrite.
|
||||
- `UPDATE` of existing points generally must go through `OPENQUERY`:
|
||||
```sql
|
||||
SELECT * FROM OPENQUERY(INSQL,
|
||||
'update History set Value = 40
|
||||
where TagName = ''LeakTest_Rate''
|
||||
and DateTime = ''2026-06-18 10:00:00.000''');
|
||||
```
|
||||
|
||||
### Constraints / gotchas
|
||||
|
||||
- **Real-time window:** values are accepted roughly **-30 s to +999 ms** around Historian time; outside that, a value sent as real-time/streamed may be **discarded**. Sync clocks for current-time inserts.
|
||||
- **Back-dating originals:** to insert *original* (non-streamed) data into the past, the system parameter **`AllowOriginals`** must permit it; otherwise you can only write revisions. Late/back-filled inserts trigger summary recomputation.
|
||||
- **Tag must accept manual data** — feed values into a manually-acquired / MDAS-style tag (or a tag configured so the Historian isn't expecting IDAS data). Tag ownership governs acceptance.
|
||||
- **Value semantics differ from a relational row:** a stored value represents a *change that persists until superseded by a later timestamp* (step/sample-and-hold), not a discrete row. Timestamp rounding can make an insert look like a duplicate of the original point.
|
||||
|
||||
---
|
||||
|
||||
## 2. Registering (creating) NEW tags via SQL
|
||||
|
||||
Tag definitions live in **normal SQL config tables** in the `Runtime` database (not extension tables). Insert the definition, then **commit** to activate it.
|
||||
|
||||
### Config tables (insert target by type)
|
||||
|
||||
| Tag type | Config table | Database Reference pg. |
|
||||
|---|---|---|
|
||||
| Analog | `AnalogTag` | ~294 |
|
||||
| Discrete | `DiscreteTag` | ~296 |
|
||||
| String | `StringTag` | ~299 |
|
||||
|
||||
### Dependency order (create these first if they don't exist)
|
||||
|
||||
`IDAS → IOServer → Topic → (EngineeringUnits for analog / MessagePairs for discrete) → tag`
|
||||
|
||||
The export/import scanner makes no attempt to resolve ordering, so parents must precede children. For **SQL/SDK-fed (manual) tags**, set the acquisition type so the Historian does **not** expect IDAS data — these tags receive values only from your `INSERT`s (Section 1).
|
||||
|
||||
### Method
|
||||
|
||||
1. `INSERT` the row(s) into `AnalogTag` / `DiscreteTag` / `StringTag` with the required columns (`TagName`, storage/acquisition keys, type-specific fields such as `MinEU`/`MaxEU`/`EngUnit` for analog or message pair for discrete).
|
||||
2. Activate the pending config:
|
||||
```sql
|
||||
EXEC aaCommitChanges;
|
||||
```
|
||||
This is the T-SQL equivalent of **"Commit Pending Changes"** in the System Management Console; config changes on a running Historian don't take effect until committed. (`aaCommitChangesAtStartup` is the deferred-at-restart variant.)
|
||||
|
||||
> **Exact column lists vary** and are column-heavy (storage node, acquisition type, storage type/rate, scaling, raw type, etc.). Confirm against the **AVEVA Historian Database Reference**, `AnalogTag`/`DiscreteTag`/`StringTag` sections (pp. ~294–299) for your version before scripting.
|
||||
|
||||
### Alternatives to raw config-table INSERT
|
||||
|
||||
- **CSV import** — the *Database Configuration Export/Import* utility (sectioned text file: `:(IOServer)`, `:(Topic)`, `:(AnalogTag)`, `:(DiscreteTag)`, `:(StringTag)`, …). Best for bulk tag creation; copy an existing tag's exported row, change the name/params.
|
||||
- **Historian SDK** — programmatic tag creation (.NET Framework; pulls HCAL back in).
|
||||
- **SMC GUI** — manual, one tag at a time (right-click Topic → New Analog/Discrete/String Tag → Commit Pending Changes).
|
||||
|
||||
---
|
||||
|
||||
## 3. Quick template (manual tag → values), end to end
|
||||
|
||||
```sql
|
||||
-- 1) Define a manual analog result tag (illustrative columns — verify vs Database Reference)
|
||||
INSERT INSQL.Runtime.dbo.AnalogTag (TagName, /* storage/acquisition + EU columns */ ...)
|
||||
VALUES ('LeakTest_Rate', /* ... */);
|
||||
|
||||
-- 2) Activate it
|
||||
EXEC aaCommitChanges;
|
||||
|
||||
-- 3) Write values
|
||||
INSERT INSQL.Runtime.dbo.History (DateTime, TagName, Value, QualityDetail, wwVersion)
|
||||
VALUES (SYSDATETIME(), 'LeakTest_Rate', 0.42, 0, 'Latest');
|
||||
```
|
||||
|
||||
For a string outcome tag, swap `AnalogTag`→`StringTag` and `History`/`Value(float)`→`StringHistory`/`Value(string)`.
|
||||
|
||||
---
|
||||
|
||||
## Alarms / events (why they're not here)
|
||||
|
||||
Alarms and events cannot be SQL-inserted into the high-speed (history-block) store — it is populated exclusively by an Application Engine configured as **Alarm Provider** (with storage-to-Historian enabled). The `v_AlarmHistory` / `v_AlarmHistory2` / `v_AlarmEventHistory2` views are **read-only** retrieval surfaces.
|
||||
|
||||
- **Want a real alarm/event** (live + historical, visible in alarm clients): raise it from an AppServer attribute alarm or the `LogDataChangeEvent` event primitive — not SQL.
|
||||
- **Want a historical-only event record** in `dbo.Events`: the documented writer is the Historian SDK; those records are never raised in the live A&E system. A direct `INSERT` into `dbo.Events` is **undocumented/unsupported** and unverified for high-speed persistence — avoid for production.
|
||||
- **Recommended:** record process outcomes as the tags in Sections 1–2, and (if an event-style query surface is needed) put a SQL **view** over the result tags.
|
||||
|
||||
---
|
||||
|
||||
*Reference compiled from AVEVA Historian documentation (Database Reference, Administration Guide, Retrieval Guide, Concepts Guide) and AVEVA community guidance. Verify exact table columns and system-parameter behavior against the Database Reference for your specific version (2020 / 2023 R2) before production use.*
|
||||
@@ -1,5 +1,16 @@
|
||||
# otopcua-uns-loader
|
||||
|
||||
> ⚠️ **STALE w.r.t. OtOpcUa's current model (as of ~2026-06-12).** OtOpcUa retired the
|
||||
> `SystemPlatform` namespace kind, the galaxy **mirror**, alias tags, and the namespace-kind
|
||||
> driver rule: **Galaxy is now a standard `Equipment`-kind driver**, and a galaxy point is an
|
||||
> ordinary equipment `Tag` bound to `GalaxyMxGateway` with `TagConfig.FullName`. The
|
||||
> SystemPlatform-mirror `populate` and the VirtualTag+Script `populate-equipment` paths below no
|
||||
> longer match the server. Also note: a **headless deploy now exists** — `POST
|
||||
> http://localhost:9200/api/deployments` with header `X-Api-Key: docker-dev-deploy-key` (the "no
|
||||
> SQL/REST/CLI trigger" claim below is outdated). To drive the new model this tool would need
|
||||
> reworking to emit equipment `Tag` rows directly. `galaxy-hierarchy.json` (the raw Galaxy DEV
|
||||
> pull) is still a valid source. Background: `OtOpcUa/docs/plans/2026-06-12-galaxy-standard-driver-design.md`.
|
||||
|
||||
A **reloadable** populate-and-verify tool for the OtOpcUa galaxy Unified Namespace.
|
||||
Recreates a UNS load grounded in the real AVEVA Galaxy **DEV** hierarchy (the 40
|
||||
`TestMachine` instances) and verifies it streams **live values** on OPC UA — so
|
||||
|
||||
Reference in New Issue
Block a user