# ArchestrA Object Toolkit (AOT) Reference Material LLM-oriented copy of the AVEVA / Wonderware *ArchestrA Object Toolkit 2014 v4.0* documentation, converted from the shipped CHM files. Original CHMs live with the AOT install at `C:\Program Files (x86)\Wonderware\Toolkits\ArchestrA Object\Docs\`. ## Layout - [`dev-guide/`](dev-guide/README.md) — Development Guide: chapters and appendices on object design, primitives, attributes, internationalization, building/versioning, debugging, and best practices. - [`reference/`](reference/README.md) — API Reference for the `ArchestrA.Toolkit` namespace: 69 types (classes, structs, enums) with members and code samples. - [`Samples/`](Samples) — Verbatim AOT 2014 sample Visual Studio solutions (`Monitor`, `Watchdog`). C# `.sln` plus per-tier projects (``, `Configtime`, `Editor`, `Runtime`). Vendor samples — do not modify unless the user asks. ## Key concepts to keep straight When the user asks AOT questions, these distinctions matter: - **ApplicationObject vs. Primitive.** ApplicationObjects model real-world equipment (pump, valve). Primitives are reusable code/attribute modules composed into objects. Every object implicitly contains the hidden "Common" primitive. - **Three project tiers per object.** An AOT object is split across `*Configtime` (config-time logic in the IDE), `*Runtime` (deployed runtime behavior), and `*Editor` (custom editor form derived from `aaBaseEditorForm`). The samples follow this exact tier split. - **Build artifacts.** Building an ApplicationObject produces an `.aaPDF`; a reusable primitive produces an `.aaPRI`. Building requires Visual Studio launched with administrator privileges. - **`CMx*` value wrappers.** Attribute values are not raw .NET types — they are wrapped in `CMxString`, `CMxInteger`, `CMxFloat`, `CMxBoolean`, etc. (and their `*Array` siblings). `CMxValue`/`CMxType`/`CMxVariant` sit above them. Indirects use `CMxIndirect` / `CMxIndirectBase` / `CMxIndirectWriteOnly`. - **Event-arg classes** (`SetHandlerEventArgs`, `ConfigtimeSetHandlerEventArgs`, `RuntimeSetHandlerEventArgs`, `RuntimeStartupEventArgs`, etc.) are how user code hooks into the object lifecycle. ## Working in this repo - Treat [`dev-guide/`](dev-guide/README.md) and [`reference/`](reference/README.md) as authoritative source-of-truth when answering AOT questions; they were converted from the official AVEVA CHMs. Cite the specific Markdown file when relevant. - The dev-guide chapter ordering matches the original CHM TOC (`01-` … `09-`, then `appendix-*`). Prefer the most specific file (e.g., attribute categories live in [`appendix-f-attribute-categories.md`](dev-guide/appendix-f-attribute-categories.md), security classifications in [`appendix-e-security-classifications.md`](dev-guide/appendix-e-security-classifications.md)). - The samples ([`Monitor`](Samples/Monitor), [`Watchdog`](Samples/Watchdog)) are the canonical worked examples — refer to them for patterns like the three-tier project split, `[AObject]` / `[ObjectAttributes.*]` decoration, dictionary (`.aaDCT`) wiring, and reusable-primitive references (`[AReusablePrimitiveRef]`). - No build/test commands apply at this folder root. To actually build a sample, open it in Visual Studio (run as Administrator) with the AOT installed — not from this directory. ## Resource index — by task | Task | Go to | | --- | --- | | Conceptual overview, workflow, UI tour | [`dev-guide/01-overview.md`](dev-guide/01-overview.md) | | Planning an object's shape (attributes, primitives, virtuals) | [`dev-guide/02-object-design.md`](dev-guide/02-object-design.md) | | Visual Studio project setup for AOT | [`dev-guide/03-working-with-projects.md`](dev-guide/03-working-with-projects.md) | | Defining an ApplicationObject in the Object Designer | [`dev-guide/04-defining-application-objects.md`](dev-guide/04-defining-application-objects.md) | | Defining a reusable primitive | [`dev-guide/05-defining-primitives.md`](dev-guide/05-defining-primitives.md) | | Attribute configuration, set handlers, locking | [`dev-guide/06-configuring-attributes.md`](dev-guide/06-configuring-attributes.md) | | Localization / multilingual dictionaries | [`dev-guide/07-internationalizing.md`](dev-guide/07-internationalizing.md) | | Building `.aaPDF` / `.aaPRI`, versioning, deployment | [`dev-guide/08-building-and-versioning.md`](dev-guide/08-building-and-versioning.md) | | Attaching the VS debugger to Application Server | [`dev-guide/09-debugging.md`](dev-guide/09-debugging.md) | | Programming techniques and recommended workflow | [`dev-guide/appendix-a-ref-guide.md`](dev-guide/appendix-a-ref-guide.md) | | Best practices (config-time, run-time, editor, quality, naming) | [`dev-guide/appendix-a-best-practices.md`](dev-guide/appendix-a-best-practices.md) | | Sample project walkthroughs | [`dev-guide/appendix-b-sample-projects.md`](dev-guide/appendix-b-sample-projects.md) | | ArchestrA data type catalog (`MxDouble`, `MxBoolean`, …) | [`dev-guide/appendix-d-data-types.md`](dev-guide/appendix-d-data-types.md) | | Security classifications (Free Access, Operate, Tune, …) | [`dev-guide/appendix-e-security-classifications.md`](dev-guide/appendix-e-security-classifications.md) | | Attribute categories (Configurable, Calculated, Writeable_*, …) | [`dev-guide/appendix-f-attribute-categories.md`](dev-guide/appendix-f-attribute-categories.md) | | API lookup for any `ArchestrA.Toolkit` type | [`reference/README.md`](reference/README.md) (one file per type) | | Worked C# example, three-tier object | [`Samples/Monitor/`](Samples/Monitor) | | Worked C# example with stats sub-project | [`Samples/Watchdog/`](Samples/Watchdog) | ## Common gotchas These trip people up regularly when working in AOT / System Platform. Long-form versions live in [`dev-guide/appendix-a-best-practices.md`](dev-guide/appendix-a-best-practices.md); summarized here so they surface without a doc dive. - **Visual Studio must run as Administrator** to build an AOT object. Builds will fail or produce no `.aaPDF` otherwise. - **No DeviceIntegration objects.** AOT 2014 cannot create DI objects — only ApplicationObjects and reusable primitives. - **Galaxy Dump/Load bypasses the editor.** Validation must live in `OnValidate` (config-time), not in the editor form. Editor-only validation is silently skipped during a Galaxy Load. - **Set handlers must accept "set to current value" silently.** Rejecting a no-op set causes spurious noise during Dump/Load. Don't reject just because the attribute isn't currently editable. - **Avoid write-only attributes that mutate object shape.** If a set handler adds/renames/removes a primitive based on a value that isn't readable back, Dump/Load can't reproduce the object. Expose the state as a readable array instead. - **Engine scans are ~100 µs budgets.** Runtime methods must be non-blocking and short. Push slow/blocking work to a thread, and tear those threads down on shutdown — otherwise the engine "overscans". - **Quality is not enforced against value.** A `Good`-quality attribute can still hold `NaN`; a `Bad`-quality attribute can hold a normal-looking number. Always check both before using a value. - **`Initializing` is a substate of `Bad`.** It's transient (until first input arrives). Don't raise "bad value" alarms while a value is `Initializing`, or you'll get transient alarms on every OnScan. - **Don't write through the wrapper to set quality on Input/Output/InputOutput attributes.** Unsupported, and may cause unexpected I/O writes. - **OnScan/OffScan quality discipline.** Set CalculatedQuality attributes to `Bad` on OffScan and `Good` (or `Initializing`) on OnScan. Forgetting this leaves stale-but-`Good` values after the object stops scanning. - **Outputs on startup.** The default contract is "object mirrors PLC" — never auto-write to the field on startup/deploy/OnScan unless you're explicitly implementing the rare reverse case. Use `ESTARTUPCONTEXT` to detect why startup happened. - **Failover/dynamic attributes need explicit calls.** Call `UpdateDynamicAttributeData()` after changing a dynamic attribute's name/type/category/security/set-handler-flag, `CheckpointDynamicAttributeData()` after value changes, and `RestoreDynamicAttributes()` from the Startup handler. Skipping any of these silently breaks failover. - **Quarantine state is sticky.** An unhandled exception in a primitive freezes its set handlers and `Execute` until the object is undeployed — attributes are still readable for forensics, but the object is effectively dead. - **Naming restrictions are strict.** Spaces and `. + - * / \ = ( ) \` ~ ! % ^ & @ [ ] { } | : ; " , < > ?` are invalid in ArchestrA names. Each segment between periods is capped at 32 chars; full attribute names cap at 329 chars, primitives at 255. Localized characters work in *external* names only, not internal names. - **Logger is for trapped errors and dev diagnostics, not operator info.** Per-scan logging will tank performance; gate any retained diagnostic logging behind a flag. - **`SendEvent` (Application Data Change) is for object-initiated changes only.** Don't fire it for user/operator sets — those are already logged by the infrastructure, and you'll double-log. ## Maintenance When adding new tools, samples, or doc sets, update **both** this README and the root [`../CLAUDE.md`](../CLAUDE.md) so the task → resource map stays consistent. See [`../DOCS-GUIDE.md`](../DOCS-GUIDE.md) for the full doctrine.