# 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 (`<Name>`, `<Name>Configtime`, `<Name>Editor`, `<Name>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.
