docs: add MES + Delmia-DNC integration API/MXAccess specs
mes-delmia-integration-api.md: endpoints, request/response DTOs, and the MXAccess flag handshake for MESAPI (in-repo MesNotifier) and DelmiaIntegration (DNC Downloader.asmx -> WWNotifier /notify -> Galaxy $DelmiaReceiver). mesrec.md / nj.md: live Galaxy receiver + reactor attribute references.
This commit is contained in:
@@ -0,0 +1,377 @@
|
||||
# MES and Delmia-DNC integrations — API & MXAccess write specification
|
||||
|
||||
Documents two existing Wonderware integrations hosted on the `ZimmerBiomet` Gitea org
|
||||
(`http://wonder-app-vd03.zmr.zimmer.com:3000`):
|
||||
|
||||
| Integration | Repo | What it does | Who does the MXAccess write |
|
||||
|---|---|---|---|
|
||||
| **MES** | [`ZimmerBiomet/MESAPI`](http://wonder-app-vd03.zmr.zimmer.com:3000/ZimmerBiomet/MESAPI) (solution `WWSupport`) | REST API the Camstar MES calls to move-in / move-out work orders against a machine, and to read machine alarm status | **The service itself** (`MesNotifier`, in-repo) |
|
||||
| **Delmia DNC** | [`ZimmerBiomet/DelmiaIntegration`](http://wonder-app-vd03.zmr.zimmer.com:3000/ZimmerBiomet/DelmiaIntegration) | Pull an NC/recipe document from the DELMIA/Apriso (Intercim) DNC server and push the resulting recipe-download notification into Wonderware | **An external receiver service** at `wonder-app-vd01:9001/notify`; the actual flag handshake is implemented in the Galaxy `$DelmiaReceiver` object (`ProcessRecipe`/`Reset` scripts) — *not* in this repo |
|
||||
|
||||
Both integrations talk to AVEVA System Platform ("Galaxy") through **MXAccess COM**
|
||||
(`ArchestrA.MxAccess.LMXProxyServerClass`) and use the same general pattern:
|
||||
|
||||
> **Handshake pattern** — read a *ready* flag → write the data tags → set a *trigger* flag
|
||||
> → wait (bounded by a timeout) for a *complete* flag → read a *success* flag + *error text*
|
||||
> → return the result and unsubscribe.
|
||||
|
||||
All facts below are taken verbatim from source at the repo `master` branch (cloned
|
||||
2026-06-17) unless explicitly marked **(inferred)**.
|
||||
|
||||
---
|
||||
|
||||
## 1. MES integration — `MESAPI` / `WWSupport`
|
||||
|
||||
### 1.1 Topology & hosting
|
||||
|
||||
```
|
||||
Camstar MES ──HTTPS/JSON──▶ WWSupport API (ServiceStack self-host)
|
||||
│ ├─ SQL Server "BT" (machine lookup by SAPID, alarm catalog)
|
||||
│ └─ MXAccess COM (LMXProxyServerClass, client "MesNotifier")
|
||||
▼
|
||||
Galaxy object {MachineCode}.MesReceiver.* (move-in / move-out tags)
|
||||
Galaxy object {MachineCode}.{AlarmName}.* (alarm attributes)
|
||||
```
|
||||
|
||||
- **Framework:** ServiceStack, self-hosted via `AppSelfHostBase` (`AppHost : base("APIServer", typeof(MesServices).Assembly)`), .NET Framework, run as a Windows service.
|
||||
- **Listen URL (per environment, `App.config` → `HttpListener`):**
|
||||
- DEV `http://*:9501/` · QA `http://*:9500/` · PROD `http://*:9500/`
|
||||
- **Database (`App.config` → connection `BatchDB`, DB `BT`):**
|
||||
- DEV `wonder-sql-vd01.zmr.zimmer.com` · QA `wondersqlqa.zmr.zimmer.com` · PROD (same form). User `wonderapp`.
|
||||
- **Auth:** every operation is decorated `[Authenticate]` + `[RequiredRole("MESAPI")]` (`MesServices.cs`).
|
||||
`AppHost` registers an `AuthFeature` with two providers: `ApiKeyAuthProvider` and `LdapAuthProvider`.
|
||||
- Unauthenticated → **401**; authenticated without the `MESAPI` role → **403**.
|
||||
- **Serialization:** `JsConfig.IncludeNullValues = true` (null fields ARE emitted in JSON). `PostmanFeature` + `OpenApiFeature` (Swagger) are enabled.
|
||||
- **MES counterpart object:** the live Galaxy attribute listing for the receiver object is in
|
||||
[`mesrec.md`](mesrec.md) (`$MESReceiver` template). Note the API binds tags under the contained
|
||||
name `MesReceiver` (i.e. `{MachineCode}.MesReceiver.<tag>`).
|
||||
|
||||
### 1.2 Endpoints (inputs / outputs)
|
||||
|
||||
Routes come from `[Route(...)]` on the request DTOs; all are **POST**, JSON in / JSON out, handled by `MesServices.Any(...)` which resolves a per-request `MesNotifier`.
|
||||
|
||||
#### `POST /mes/movein` → `MoveInResponse`
|
||||
|
||||
Request `MoveInRequest`:
|
||||
|
||||
| Field | Type | Notes |
|
||||
|---|---|---|
|
||||
| `SAPID` | string | machine key; looked up in `BT.Machine` to get `Machine.Code` |
|
||||
| `OperatorName` | string | |
|
||||
| `JobSequenceNumber` | string | |
|
||||
| `WorkOrders` | `List<WorkOrderInfo>` | each = `{ WorkOrderNumber: string, PartNumber: string }` |
|
||||
|
||||
Response `MoveInResponse`: `WasSuccessful` (bool), `ErrorText` (string), `BatchID` (int?, only set if machine returns non-zero).
|
||||
|
||||
#### `POST /mes/moveout` → `MoveOutResponse`
|
||||
|
||||
Request `MoveOutRequest`: `SAPID` (string), `OperatorName` (string), `WorkOrders` (`List<WorkOrderInfo>`).
|
||||
*(Move-out has no `JobSequenceNumber`.)*
|
||||
Response `MoveOutResponse`: identical shape to `MoveInResponse` (`WasSuccessful`, `ErrorText`, `BatchID`).
|
||||
|
||||
#### `POST /mes/alarmstatus` → `AlarmStatusResponse`
|
||||
|
||||
Request `AlarmStatusRequest`:
|
||||
- `MachineFilter` = `{ MachineID: int?, SAPID: string, ZTag: string, Code: string }` (any one identifies the machine)
|
||||
- `AlarmFilter` = `{ NameFilter: string, MinSeverity: int?, MaxSeverity: int?, IncludeTriggered: bool=true, IncludeAcked: bool=true, FlaggedOnly: bool=false }`
|
||||
|
||||
#### `POST /mes/simplealarmstatus` → `AlarmStatusResponse`
|
||||
|
||||
Request `SimpleAlarmStatusRequest`: `SAPID` (string). Internally loads only alarms with `FlaggedForMES == true` for that machine.
|
||||
|
||||
Response `AlarmStatusResponse` (both alarm endpoints): `WasSuccessful` (bool), `ErrorText` (string), `Alarms` (`List<AlarmInfo>`).
|
||||
|
||||
`AlarmInfo`: `Name` (string), `HierarchicalName` (string, `{Code}.{AlarmName}`), `Description` (string), `IsFlaggedForMES` (bool), `Severity` (int), `StatusCode` (string — `"Triggered"` or `"Triggered.Acked"`), `TriggeredDT` (DateTime), `AckDT` (DateTime?), `AckComment` (string).
|
||||
|
||||
### 1.3 MXAccess connection model
|
||||
|
||||
`MesNotifier` owns one MXAccess proxy for the request:
|
||||
|
||||
```csharp
|
||||
_lmxProxy = new ArchestrA.MxAccess.LMXProxyServerClass();
|
||||
_lmxHandle = _lmxProxy.Register("MesNotifier");
|
||||
_lmxProxy.OnDataChange += ...; // value updates resolve pending read/OnValue tasks
|
||||
_lmxProxy.OnWriteComplete += ...; // write acks resolve pending write tasks
|
||||
```
|
||||
|
||||
Tags are added with `AddItem` + `AdviseSupervisory` (subscribe), updated via `OnDataChange`,
|
||||
and removed with `UnAdvise` + `RemoveItem` on cleanup. Reads/writes are wrapped as `Task<bool>`
|
||||
that complete on the corresponding callback or **fail (`false`) on cancellation/timeout**.
|
||||
A read is considered valid only if MXAccess **quality == 192** ("good").
|
||||
|
||||
**Target selection:** request `SAPID` → `db.Single<Machine>(x => x.SAPID == SAPID)` → `Machine.Code`
|
||||
becomes the tag prefix. Move tags live under `{Code}.MesReceiver.*`; alarm tags under
|
||||
`{Code}.{MachineAlarm.Name}.*` (alarm catalog from `db.Select<MachineAlarm>(...)`).
|
||||
|
||||
### 1.4 Tag mappings
|
||||
|
||||
**Move-in** (`MesMoveInTagset`, all `{Code}.MesReceiver.<tag>`):
|
||||
|
||||
| Tag | Type | Dir | Role | Source field |
|
||||
|---|---|---|---|---|
|
||||
| `MoveInReadyFlag` | bool | read | gate — must be `true` before writing | — |
|
||||
| `MoveInFlag` | bool | **write** | **trigger** — set `true` last | — |
|
||||
| `MoveInCompleteFlag` | bool | read | completion — handshake waits on this | — |
|
||||
| `MoveInSuccessfulFlag` | bool | read | result | → `response.WasSuccessful` |
|
||||
| `MoveInErrorText` | string | read | result | → `response.ErrorText` |
|
||||
| `MoveInBatchID` | int | read | result | → `response.BatchID` (if ≠ 0) |
|
||||
| `MoveInOperatorName` | string | write | data | `request.OperatorName` |
|
||||
| `MoveInJobSequenceNumber` | string | write | data | `request.JobSequenceNumber` |
|
||||
| `MoveInNumberWorkOrders` | int | write | data | `request.WorkOrders.Count` |
|
||||
| `MoveInWorkOrderNumbers[]` | string[] | write | data (fixed length 50) | `WorkOrders.Select(w => w.WorkOrderNumber)` |
|
||||
| `MoveInPartNumbers[]` | string[] | write | data (fixed length 50) | `WorkOrders.Select(w => w.PartNumber)` |
|
||||
|
||||
**Move-out** (`MesMoveOutTagset`): identical set with `MoveOut` prefix, **minus** `JobSequenceNumber`
|
||||
(`MoveOutReadyFlag`, `MoveOutFlag`, `MoveOutCompleteFlag`, `MoveOutSuccessfulFlag`, `MoveOutErrorText`,
|
||||
`MoveOutBatchID`, `MoveOutOperatorName`, `MoveOutNumberWorkOrders`, `MoveOutWorkOrderNumbers[]`, `MoveOutPartNumbers[]`).
|
||||
|
||||
**Alarms** (`AlarmTagset`, all `{Code}.{AlarmName}.<attr>`): `Quality` (int), `InAlarm` (bool),
|
||||
`TimeAlarmOn` (DateTime), `DescAttrName` (string), `Acked` (bool), `TimeAlarmAcked` (DateTime?), `AckMsg` (string).
|
||||
|
||||
### 1.5 The handshake — `MesNotifier.MoveIn` (move-out is identical with `MoveOut*` tags)
|
||||
|
||||
Whole operation is bounded by **`new CancellationTokenSource(30000)` = 30 s**.
|
||||
|
||||
1. **Look up machine** by `SAPID`. Not found → `WasSuccessful=false`, `ErrorText="Failed to find machine with SAPID '{SAPID}'"`, return.
|
||||
2. **Subscribe** to every move-in tag (`Advise(t, cts)`), `await Task.WhenAll(...)`. Any subscription that fails / quality ≠ 192 → `ErrorText="Failed to connect to machine"`.
|
||||
3. **Check ready flag:** `if (!MoveInReadyFlag.Value)` → `ErrorText="Machine move in ready flag not set to true"`, stop.
|
||||
4. **Arm completion watch:** `Task<bool> flagTask = MoveInCompleteFlag.OnValue(true, cts);` (completes when the flag goes `true`, or `false` on the 30 s timeout).
|
||||
5. **Write data + trigger (in parallel, trigger last):** `MoveInOperatorName`, `MoveInJobSequenceNumber`, `MoveInNumberWorkOrders`, `MoveInPartNumbers[]` (padded to 50), `MoveInWorkOrderNumbers[]` (padded to 50), then `MoveInFlag = true`. `await Task.WhenAll(writeTasks)`; any write `!= true` → `ErrorText="Failed to write move in information to machine"`.
|
||||
6. **Wait for completion:** `await Task.WhenAll(flagTask)`.
|
||||
- `flagTask.Result == true` → read results: `WasSuccessful = MoveInSuccessfulFlag.Value`, `ErrorText = MoveInErrorText.Value`, `BatchID = MoveInBatchID.Value` (if ≠ 0).
|
||||
- `flagTask.Result == false` (timed out) → `WasSuccessful=false`, `ErrorText="Timeout waiting for move in information to be processed"`.
|
||||
7. **Cleanup:** `Tags.ForEach(Unadvise)` and return.
|
||||
|
||||
```csharp
|
||||
using (var cts = new CancellationTokenSource(30000)) { // 30 s budget
|
||||
...
|
||||
if (!moveInTagset.MoveInReadyFlag.Value) { /* not-ready error */ }
|
||||
var flagTask = moveInTagset.MoveInCompleteFlag.OnValue(true, cts); // arm completion watch
|
||||
var writeTasks = new List<Task<bool>> {
|
||||
Write(moveInTagset.MoveInOperatorName.Handle, request.OperatorName, cts),
|
||||
Write(moveInTagset.MoveInJobSequenceNumber.Handle, request.JobSequenceNumber, cts),
|
||||
Write(moveInTagset.MoveInNumberWorkOrders.Handle, request.WorkOrders.Count, cts),
|
||||
Write(moveInTagset.MoveInPartNumbers.Handle, request.WorkOrders.Select(wo => wo.PartNumber).ToFixedLength(50), cts),
|
||||
Write(moveInTagset.MoveInWorkOrderNumbers.Handle, request.WorkOrders.Select(wo => wo.WorkOrderNumber).ToFixedLength(50), cts),
|
||||
Write(moveInTagset.MoveInFlag.Handle, true, cts) // TRIGGER — set last
|
||||
};
|
||||
await Task.WhenAll(writeTasks);
|
||||
await Task.WhenAll(flagTask);
|
||||
if (flagTask.Result) {
|
||||
response.WasSuccessful = moveInTagset.MoveInSuccessfulFlag.Value;
|
||||
response.ErrorText = moveInTagset.MoveInErrorText.Value;
|
||||
if (moveInTagset.MoveInBatchID.Value != 0) response.BatchID = moveInTagset.MoveInBatchID.Value;
|
||||
} else {
|
||||
response.WasSuccessful = false;
|
||||
response.ErrorText = "Timeout waiting for move in information to be processed";
|
||||
}
|
||||
moveInTagset.Tags.ForEach(Unadvise);
|
||||
}
|
||||
```
|
||||
|
||||
> There is **no busy-poll loop**: completion is event-driven via the MXAccess `OnDataChange`
|
||||
> callback; the 30 s `CancellationTokenSource` is the only timeout.
|
||||
|
||||
### 1.6 Alarm-status path
|
||||
|
||||
1. Resolve machine from `MachineFilter` (`SAPID` / `Code` / `ZTag` / `MachineID`) — wrong/missing → error.
|
||||
2. Load `MachineAlarm` rows for the machine; apply filters (`FlaggedOnly`, `MinSeverity`, `MaxSeverity`, case-insensitive `NameFilter.Contains`). *(`IncludeTriggered` is read but not used in the filter.)*
|
||||
3. Subscribe + read each alarm's `Quality` and `InAlarm` (30 s budget). Bad quality / read failure → `ErrorText="Failed to read machine alarm status"`.
|
||||
4. For alarms where `InAlarm == true`, additionally read `TimeAlarmOn`, `DescAttrName`, `Acked`, `TimeAlarmAcked`, `AckMsg`.
|
||||
5. Build `AlarmInfo` per triggered alarm; `StatusCode = "Triggered.Acked"` if acked else `"Triggered"`. If `AlarmFilter.IncludeAcked == false`, acked alarms are skipped.
|
||||
6. Unsubscribe; on failure `Alarms` is cleared.
|
||||
|
||||
### 1.7 Outputs / error handling (MES)
|
||||
|
||||
- **Transport status is always 200** for handled responses — success/failure is carried by the body's `WasSuccessful` flag + `ErrorText`. (401/403 only from the auth layer.)
|
||||
- Success: `{ "WasSuccessful": true, "ErrorText": null, "BatchID": <int|null> }`.
|
||||
- Failure/timeout: `{ "WasSuccessful": false, "ErrorText": "<message>", "BatchID": null }`.
|
||||
- Distinct `ErrorText` values: machine-not-found, "Failed to connect to machine", "…ready flag not set to true", "Failed to write … to machine", "Timeout waiting for … to be processed", "Failed to read machine alarm status".
|
||||
|
||||
---
|
||||
|
||||
## 2. Delmia-DNC integration — `DelmiaIntegration` (+ Galaxy `$DelmiaReceiver`)
|
||||
|
||||
### 2.1 Topology — three hops
|
||||
|
||||
```
|
||||
Operator (DelmiaIntegration.exe WinForms)
|
||||
│ ① DelmiaClient ──HTTP POST (form-url-encoded)──▶ DELMIA/Apriso DNC "Downloader.asmx"
|
||||
│ (e.g. http://dnc-app-vd01.zmr.zimmer.com/IntercimService/Downloader.asmx)
|
||||
│ ◀── XML (SearchResults / DownloadResult, ns http://intercim.com/ruleset) ──
|
||||
│ ② recipe file written to disk; WWNotifier.exe launched with CLI args
|
||||
▼
|
||||
WWNotifier.exe ──HTTP POST (JSON RecipeDownload)──▶ WW receiver service (http://wonder-app-vd01:9001/notify)
|
||||
◀── JSON RecipeDownloadResult ── │ ③ MXAccess COM write
|
||||
▼
|
||||
Galaxy object {machine}.$DelmiaReceiver.* (recipe tags + flags)
|
||||
+ ArchestrA scripts ProcessRecipe / Reset
|
||||
```
|
||||
|
||||
**Assemblies in the repo:** `DelmiaContracts` (XML DTO library), `DelmiaIntegration` (`DelmiaClient` + WinForms UI),
|
||||
`WWNotifier.exe` (console notifier), plus test harnesses (`AdminTestUtil`, `DownloadTestUtil`, `TestUI`).
|
||||
|
||||
> **Scope note.** Hops ① and ② are fully in this repo. Hop ③ — the service at `:9001/notify`
|
||||
> that actually performs the MXAccess write — is **not** in the `ZimmerBiomet` Gitea org; only the
|
||||
> JSON contract (below) and the Galaxy-side `$DelmiaReceiver` object (scripts + attributes, exported
|
||||
> under `AA_EXPORT/`) are available. `WWNotificationSystem` *also* uses MXAccess but is an unrelated
|
||||
> tag→email alerting service (port `:9876`, client name `WWNotifierMonitor`) — **not** the recipe receiver.
|
||||
|
||||
### 2.2 DNC server interface (`DelmiaClient`, hop ①)
|
||||
|
||||
- **Transport:** `HttpClient.PostAsync` with `FormUrlEncodedContent`; response is XML deserialized
|
||||
with `XmlSerializer`. Base URL is `DelmiaClient.URL`; per-call `Timeout` default **30 s**.
|
||||
Action is appended to the base URL (`URL.TrimEnd('/') + "/<Action>"`).
|
||||
- **Base URL (from `AdminTestUtil` `DefaultURL`):** `http://dnc-app-vd01.zmr.zimmer.com/IntercimService/Downloader.asmx`.
|
||||
- On any exception the client returns a result object with the error in `ErrorMessage` /
|
||||
`TransferSuccessful=false` (it does not throw to the caller).
|
||||
|
||||
| Method (sync + `…Async`) | POST action | Form fields | Returns |
|
||||
|---|---|---|---|
|
||||
| `Search` | `/Search` | `username, machineID, partNumber, operationNumber` | `SearchResults` |
|
||||
| `RequestProvenDocument` | `/RequestProvenDocument` | `username, machineID, partNumber, operationNumber, workOrderNumber` | `DownloadResult` |
|
||||
| `RequestDocument` | `/RequestDocument` | `username, machineID, partNumber, operationNumber, workOrderNumber, documentKey` | `DownloadResult` |
|
||||
|
||||
DTO field lists (`DelmiaContracts`, XML namespace `http://intercim.com/ruleset`):
|
||||
|
||||
- **`SearchResults`**: `Results` (`List<SearchResult>`), `ErrorMessage` (string).
|
||||
- **`SearchResult`**: `ShopOrderKey` (int), `ShopOrderID` (string), `ShopOrderStatus` (string),
|
||||
`ShopOrderOperKey` (int), `ShopOrderOperID` (string), `ShopOrderOperStatus` (string),
|
||||
`DocumentKey` (int), `DocumentObjectID` (int, with `…Specified` flag), `DocumentName` (string),
|
||||
`DocumentRev` (string), `DocumentStatus` (string), `DocumentURL` (string), `PartID` (string), `PartRev` (string).
|
||||
- **`DownloadResult`**: `UserKey` (int), `UserName` (string), `UserSite` (string), `MachineKey` (int),
|
||||
`MachineID` (string), `MachineSite` (string), `WorkOrderNumber` (string), `ShopOrderKey` (int),
|
||||
`ShopOrderID` (string), `ShopOrderStatus` (string), `ShopOrderOperKey` (int), `ShopOrderOperID` (string),
|
||||
`ShopOrderOperStatus` (string), `DocumentKey` (int), `DocumentName` (string), `DocumentRev` (string),
|
||||
`DocumentStatus` (string), `PartID` (string), `PartRev` (string), **`TransferSuccessful` (bool)**,
|
||||
**`ErrorMessage` (string)**.
|
||||
- **`MachineInfo`** (contract present; not called by current code): `MachineKey` (int), `MachineID` (string),
|
||||
`MachineName` (string), `DownloadPath` (string), `MachineDescription` (string), `MachineSite` (string), `MachineStatus` (string).
|
||||
- **`UserInfo`**: `UserKey` (int), `UserName` (string), `UserSite` (string), `IsActive` (bool).
|
||||
|
||||
**Recipe file:** the downloaded document is a key/value recipe file parsed by `DelmiaIntegration/Models/RecipeSet.cs`
|
||||
(`KEY,VALUE` lines; typed accessors `GetString/GetInt/GetBool/GetFloat/GetDouble/...`). It is written to disk;
|
||||
its path is what gets handed to `WWNotifier` (`--downloadpath`).
|
||||
|
||||
### 2.3 WWNotifier (hop ②) — invocation & handoff contract
|
||||
|
||||
`WWNotifier.exe` (uses `CommandLineParser`); CLI options (`CommandLineOptions`):
|
||||
|
||||
| Short | Long | Required | Field |
|
||||
|---|---|---|---|
|
||||
| `-d` | `--downloadpath` | yes | `DownloadPath` (recipe file path) |
|
||||
| `-m` | `--machine` | yes | `MachineCode` |
|
||||
| `-w` | `--workorder` | yes | `WorkOrderNumber` |
|
||||
| `-p` | `--partnumber` | yes | `PartNumber` |
|
||||
| `-s` | `--seqop` | no | `JobStepNumber` |
|
||||
| `-u` | `--username` | no | `Username` |
|
||||
|
||||
Config (`WWNotifier/App.config`): `NotifyURL = http://wonder-app-vd01.zmr.zimmer.com:9001/notify`
|
||||
(comma-separated list allowed — tried in order until one succeeds), `NotifyTimeout = 30` (seconds,
|
||||
applied as the global Flurl HTTP timeout).
|
||||
|
||||
Handoff (Flurl): `url.PostJsonAsync(recipeDownload).ReceiveJson<RecipeDownloadResult>()`.
|
||||
|
||||
- **Request body `RecipeDownload`** (JSON): `MachineCode`, `DownloadPath`, `WorkOrderNumber`, `PartNumber`, `JobStepNumber`, `Username` (all string).
|
||||
- **Response body `RecipeDownloadResult`** (JSON): `Result` (bool), `ResultText` (string).
|
||||
- **Outputs:** prints `YES` and exit code `0` on success; prints `NO` + a message and sets exit code `-1`
|
||||
on failure (parse error, missing `NotifyURL`/`NotifyTimeout`, `Result==false`, or HTTP exception).
|
||||
*(Caveat: on a caught exception it logs `error.InnerException.Message`, which throws a NRE when there is no inner exception — so bare transport errors surface only as a generic failure.)*
|
||||
|
||||
### 2.4 MXAccess write — Galaxy `$DelmiaReceiver` object (hop ③)
|
||||
|
||||
The receiver service maps `RecipeDownload` fields onto the `$DelmiaReceiver` object instance selected by
|
||||
`MachineCode`. Object attributes (from `AA_EXPORT/.../$DelmiaReceiver` export) and their roles:
|
||||
|
||||
| Attribute | Type | Role | Maps from |
|
||||
|---|---|---|---|
|
||||
| `ReadyFlag` | Boolean | gate — receiver expects `true` before writing | — |
|
||||
| `DownloadPath` | String | data | `RecipeDownload.DownloadPath` |
|
||||
| `WorkOrderNumber` | String | data | `RecipeDownload.WorkOrderNumber` |
|
||||
| `PartNumber` | String | data | `RecipeDownload.PartNumber` |
|
||||
| `JobStepNumber` | String | data | `RecipeDownload.JobStepNumber` |
|
||||
| `Username` | String | data | `RecipeDownload.Username` |
|
||||
| `RecipeDownloadFlag` | Boolean | **trigger** — set `true` to start processing | — |
|
||||
| `RecipeProcessedFlag` | Boolean | completion — handshake waits on this | — |
|
||||
| `RecipeProcessResult` | Boolean | result | → `RecipeDownloadResult.Result` |
|
||||
| `RecipeProcessResultText` | String | result | → `RecipeDownloadResult.ResultText` |
|
||||
|
||||
*(`MachineCode` selects which receiver instance; it is not itself a written attribute.)*
|
||||
|
||||
**Galaxy-side handshake (authoritative — ArchestrA scripts on `$DelmiaReceiver`):**
|
||||
|
||||
`ProcessRecipe` (runs when `RecipeDownloadFlag` is set):
|
||||
```
|
||||
Me.RecipeDownloadFlag = false; ' clear trigger
|
||||
Me.ReadyFlag = false; ' clear ready
|
||||
try
|
||||
Me.RecipeProcessResult = true;
|
||||
Me.RecipeProcessResultText = "Success";
|
||||
catch
|
||||
Me.RecipeProcessResult = false;
|
||||
Me.RecipeProcessResultText = "Failed to read recipe file";
|
||||
endtry;
|
||||
Me.RecipeProcessedFlag = true; ' signal completion
|
||||
```
|
||||
|
||||
`Reset` (clears the slot for the next download):
|
||||
```
|
||||
Me.RecipeDownloadFlag = false; Me.RecipeProcessedFlag = false;
|
||||
Me.RecipeProcessResult = false; Me.RecipeProcessResultText = "";
|
||||
Me.DownloadPath = ""; Me.WorkOrderNumber = ""; Me.PartNumber = "";
|
||||
Me.JobStepNumber = ""; Me.Username = "";
|
||||
```
|
||||
|
||||
**Receiver-side sequence (inferred** — mirrors the MES handshake and is driven by the flags above; the C# source is not in the repo**):**
|
||||
1. resolve the `$DelmiaReceiver` instance from `MachineCode`;
|
||||
2. (optionally) verify `ReadyFlag == true`;
|
||||
3. write `DownloadPath`, `WorkOrderNumber`, `PartNumber`, `JobStepNumber`, `Username`;
|
||||
4. set `RecipeDownloadFlag = true` (trigger) → Galaxy `ProcessRecipe` fires;
|
||||
5. wait for `RecipeProcessedFlag == true`, bounded by the request timeout;
|
||||
6. read `RecipeProcessResult` → `Result`, `RecipeProcessResultText` → `ResultText`; return the `RecipeDownloadResult` JSON;
|
||||
7. `Reset` the object.
|
||||
|
||||
### 2.5 Outputs / error handling (Delmia)
|
||||
|
||||
- **DNC server call:** failures are swallowed into the returned DTO — `SearchResults.ErrorMessage`, or
|
||||
`DownloadResult.TransferSuccessful=false` + `ErrorMessage="Failed to call Delmia web service at '<URL>'."`.
|
||||
- **Notify handoff:** `RecipeDownloadResult.Result` (bool) + `ResultText` (string); `WWNotifier` exit code
|
||||
`0` (`YES`) / `-1` (`NO`).
|
||||
- **Galaxy script:** `RecipeProcessResultText` is `"Success"` or `"Failed to read recipe file"`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Side-by-side summary
|
||||
|
||||
| | MES (`MESAPI`) | Delmia DNC (`DelmiaIntegration`) |
|
||||
|---|---|---|
|
||||
| Caller | Camstar MES (HTTP/JSON) | Operator UI → DELMIA DNC server, then WWNotifier |
|
||||
| API style | ServiceStack REST, `POST /mes/*` | DNC = form-url-encoded → XML; notify = JSON POST |
|
||||
| Who writes MXAccess | the service (`MesNotifier`, in-repo) | external `:9001/notify` receiver (source not in repo) |
|
||||
| MXAccess client | `LMXProxyServerClass`, register `"MesNotifier"` | `LMXProxyServerClass` (receiver), Galaxy `$DelmiaReceiver` scripts |
|
||||
| Target object | `{MachineCode}.MesReceiver.*` | `{MachineCode}.$DelmiaReceiver` instance |
|
||||
| Ready / trigger / complete | `MoveInReadyFlag` / `MoveInFlag` / `MoveInCompleteFlag` | `ReadyFlag` / `RecipeDownloadFlag` / `RecipeProcessedFlag` |
|
||||
| Result / error | `MoveInSuccessfulFlag` / `MoveInErrorText` (+`MoveInBatchID`) | `RecipeProcessResult` / `RecipeProcessResultText` |
|
||||
| Timeout | 30 s (`CancellationTokenSource(30000)`), event-driven | 30 s HTTP (`NotifyTimeout`); Galaxy wait at receiver |
|
||||
|
||||
---
|
||||
|
||||
## 4. Sources & open gaps
|
||||
|
||||
**Repos (Gitea `ZimmerBiomet`, `master`):**
|
||||
- MES: `MESAPI` — `APIServer.ServiceInterface/MesServices.cs`, `MesNotifier.cs`,
|
||||
`Mes{MoveIn,MoveOut}Tagset.cs`, `AlarmTagset.cs`, `Tag.cs`/`OnValueTask.cs`;
|
||||
`APIServer.ServiceModel/Types/*`; `APIServer/AppHost.cs`, `App.config`.
|
||||
- Delmia: `DelmiaIntegration` — `DelmiaIntegration/DelmiaClient.cs`, `Models/RecipeSet.cs`;
|
||||
`WWNotifier/Program.cs`, `CommandLineOptions.cs`, `Models/RecipeDownload(Result).cs`, `App.config`;
|
||||
`DelmiaContracts/*`.
|
||||
|
||||
**Galaxy export (`~/Desktop/AA_EXPORT/EXTRACTED/$DelmiaReceiver`):** `scripts/ProcessRecipe.txt`,
|
||||
`scripts/Reset.txt`, `$DelmiaReceiver.top_level_attributes.csv`. MES receiver object attributes: [`mesrec.md`](mesrec.md).
|
||||
|
||||
**Open gaps / to verify against the box:**
|
||||
1. The Delmia recipe **`/notify` receiver service** source (the actual MXAccess writer at `wonder-app-vd01:9001`)
|
||||
was not found in the Gitea org — §2.4 receiver steps are inferred from the contract + Galaxy scripts.
|
||||
2. MES tag prefix in code is `{Code}.MesReceiver.*`, while the live probe in `mesrec.md` shows a top-level
|
||||
`MESReceiver_002` instance — confirm the exact contained-name/instance convention on the live Galaxy.
|
||||
3. PROD `HttpListener`/DB host values should be read from the deployed `App.config`, not assumed.
|
||||
@@ -0,0 +1,77 @@
|
||||
# MESReceiver object — attributes (wonder-app-vd03 Galaxy)
|
||||
|
||||
Source: live AVEVA Galaxy DB **`ZB`** on **wonder-app-vd03** (the MxAccessGateway box),
|
||||
read via the gateway's own `AttributesSql` (recursive `deployed_package_chain` over
|
||||
`dynamic_attribute` / `attribute_definition`) run with `sqlcmd` over ssh — `2026-06-16`.
|
||||
|
||||
## Instance probed
|
||||
- **TagName:** `MESReceiver_002` (GobjectId `5909`, ParentGobjectId `5908`, HostedBy `5049`)
|
||||
- **TemplateChain:** `$MESDemo.MESReceiver` → `$MESReceiver` → `$gUserDefined` → `$UserDefined`
|
||||
- **CategoryId:** 10, `IsArea = false`
|
||||
- There are many MESReceiver instances on this Galaxy (1,253 `MESReceiver` references in the
|
||||
`galaxy-snapshot.json` hierarchy cache). `MESReceiver_002` is representative of the template.
|
||||
|
||||
> Note: the cached `galaxy-snapshot.json` (gateway Server dir) holds the **object hierarchy only**
|
||||
> — it carries **no attributes**, so attribute discovery requires the DB query (or gRPC `galaxy-discover`).
|
||||
|
||||
## Container number
|
||||
There is **no attribute literally named `ContainerNumber`**. The MES container number is carried by:
|
||||
- **`MoveInMesContainerNum`** — String (move-in interface)
|
||||
- **`MoveOutMesContainerNum`** — String (move-out interface)
|
||||
|
||||
Full tag references: `MESReceiver_002.MoveInMesContainerNum`, `MESReceiver_002.MoveOutMesContainerNum`.
|
||||
|
||||
## MES interface UDAs (attribute-category 10, security-classification 1 = secured/operate)
|
||||
|
||||
### Move-In
|
||||
| Attribute | Type | Full tag reference |
|
||||
|---|---|---|
|
||||
| **MoveInMesContainerNum** | String | `MESReceiver_002.MoveInMesContainerNum` |
|
||||
| MoveInBatchID | Integer | `MESReceiver_002.MoveInBatchID` |
|
||||
| MoveInJobSequenceNumber | String | `MESReceiver_002.MoveInJobSequenceNumber` |
|
||||
| MoveInNumberWorkOrders | Integer | `MESReceiver_002.MoveInNumberWorkOrders` |
|
||||
| MoveInWorkOrderNumbers | String[] | `MESReceiver_002.MoveInWorkOrderNumbers[]` |
|
||||
| MoveInPartNumbers | String[] | `MESReceiver_002.MoveInPartNumbers[]` |
|
||||
| MoveInOperatorName | String | `MESReceiver_002.MoveInOperatorName` |
|
||||
| MoveInFlag | Boolean | `MESReceiver_002.MoveInFlag` |
|
||||
| MoveInReadyFlag | Boolean | `MESReceiver_002.MoveInReadyFlag` |
|
||||
| MoveInCompleteFlag | Boolean | `MESReceiver_002.MoveInCompleteFlag` |
|
||||
| MoveInSuccessfulFlag | Boolean | `MESReceiver_002.MoveInSuccessfulFlag` |
|
||||
| MoveInErrorText | String | `MESReceiver_002.MoveInErrorText` |
|
||||
|
||||
### Move-Out (symmetric; no JobSequenceNumber)
|
||||
| Attribute | Type | Full tag reference |
|
||||
|---|---|---|
|
||||
| **MoveOutMesContainerNum** | String | `MESReceiver_002.MoveOutMesContainerNum` |
|
||||
| MoveOutBatchID | Integer | `MESReceiver_002.MoveOutBatchID` |
|
||||
| MoveOutNumberWorkOrders | Integer | `MESReceiver_002.MoveOutNumberWorkOrders` |
|
||||
| MoveOutWorkOrderNumbers | String[] | `MESReceiver_002.MoveOutWorkOrderNumbers[]` |
|
||||
| MoveOutPartNumbers | String[] | `MESReceiver_002.MoveOutPartNumbers[]` |
|
||||
| MoveOutOperatorName | String | `MESReceiver_002.MoveOutOperatorName` |
|
||||
| MoveOutFlag | Boolean | `MESReceiver_002.MoveOutFlag` |
|
||||
| MoveOutReadyFlag | Boolean | `MESReceiver_002.MoveOutReadyFlag` |
|
||||
| MoveOutCompleteFlag | Boolean | `MESReceiver_002.MoveOutCompleteFlag` |
|
||||
| MoveOutSuccessfulFlag | Boolean | `MESReceiver_002.MoveOutSuccessfulFlag` |
|
||||
| MoveOutErrorText | String | `MESReceiver_002.MoveOutErrorText` |
|
||||
|
||||
## Standard ArchestrA `$UserDefined` / system attributes (also present)
|
||||
`AlarmCntsBySeverity[]`, `AlarmCntsBySeverityEnableShelved[]`, `AlarmInhibit`, `AlarmMode`,
|
||||
`AlarmModeCmd`, `AlarmMostUrgentAcked`, `AlarmMostUrgentInAlarm`, `AlarmMostUrgentMode`,
|
||||
`AlarmMostUrgentSeverity`, `AlarmMostUrgentShelved`, `AliasName`, `Area`, `CmdData`, `CodeBase`,
|
||||
`ConfigVersion`, `ContainedName`, `Container`, `Errors[]`, `ExecutionRelatedObject`,
|
||||
`ExecutionRelativeOrder`, `Extensions`, `HierarchicalName`, `Host`, `InAlarm`, `MinorVersion`,
|
||||
`PropagatedAlarmInhibit`, `ScanState`, `ScanStateCmd`, `SecurityGroup`, `ShortDesc`, `Tagname`,
|
||||
`UDAs`, `UserAttrData`, `PropagatedAlarmInhibit`.
|
||||
|
||||
## How to reproduce
|
||||
1. `MESReceiver` instances are in the gateway hierarchy cache
|
||||
`E:\ApiInstall\MxGateway\Server\galaxy-snapshot.json` (objects only, no attrs).
|
||||
2. Attribute list: run the gateway's `AttributesSql`
|
||||
(`src/.../Server/Galaxy/GalaxyRepository.cs`) scoped to one instance via
|
||||
`... WHERE g.is_template = 0 AND g.deployed_package_id <> 0 AND g.tag_name = 'MESReceiver_002'`
|
||||
in the `deployed_package_chain` anchor, then `sqlcmd -S (local) -d ZB -U wwadmin -P <pwd>`
|
||||
on the box (Galaxy creds from `MxGateway.Galaxy.ConnectionString` in the gateway appsettings).
|
||||
3. Live values would need an MXAccess read through the gateway (gRPC), not the repo SQL.
|
||||
|
||||
In OtOpcUa (Galaxy-as-standard-driver model) these bind as ordinary equipment tags:
|
||||
`Tag{ DriverInstanceId = GalaxyMxGateway, TagConfig = {"FullName":"MESReceiver_002.MoveInMesContainerNum"} }`.
|
||||
@@ -0,0 +1,212 @@
|
||||
# New Jersey — DARS reactors Z28061 / Z28062 (wonder Galaxy)
|
||||
|
||||
Source: live AVEVA Galaxy DB **`ZB`** on **wonder-app-vd03** (MxAccessGateway box), via the gateway's `AttributesSql` over `sqlcmd`/ssh — `2026-06-16`. Lists the **meaningful (user-defined, cat-10) attributes**; ArchestrA system attributes (alarm framework, identity, security) and per-field config sub-attributes (`.EngUnits`, `.TrendHi`, `.Dev.*`, history/alarm settings) and scripts are omitted.
|
||||
|
||||
## Hierarchy
|
||||
```
|
||||
NewJersey (area)
|
||||
└─ CVDAisle_1 ($CVDAisle, gobject 7243)
|
||||
├─ Z28061 ($DARSReactor, gobject 7171)
|
||||
│ ├─ Left (Left_002, $DARSReactor.Left, gobject 7172)
|
||||
│ └─ Right (Right_002, $DARSReactor.Right, gobject 7173)
|
||||
└─ Z28062 ($DARSReactor, gobject 7202)
|
||||
├─ Left (Left_003, $DARSReactor.Left, gobject 7203)
|
||||
└─ Right (Right_003, $DARSReactor.Right, gobject 7204)
|
||||
```
|
||||
(`Z28061Sim`, gobject 7146, is a simulator sibling of Z28061.)
|
||||
|
||||
## Objects
|
||||
| Object | GobjectId | Template | Compound path | UDA attrs | Total attrs |
|
||||
|---|---|---|---|---|---|
|
||||
| Left_002 | 7172 | `$DARSReactor.Left` | Z28061.Left | 72 | 1907 |
|
||||
| Left_003 | 7203 | `$DARSReactor.Left` | Z28062.Left | 72 | 1907 |
|
||||
| Right_002 | 7173 | `$DARSReactor.Right` | Z28061.Right | 72 | 1907 |
|
||||
| Right_003 | 7204 | `$DARSReactor.Right` | Z28062.Right | 72 | 1907 |
|
||||
| Z28061 | 7171 | `$DARSReactor` | Z28061 | 16 | 195 |
|
||||
| Z28062 | 7202 | `$DARSReactor` | Z28062 | 16 | 195 |
|
||||
|
||||
> Attribute sets are template-defined: `Z28061`≡`Z28062`, `Left_002`≡`Left_003`, `Right_002`≡`Right_003`. Listed once per template.
|
||||
|
||||
## $DARSReactor — Z28061 / Z28062 (reactor body)
|
||||
|
||||
**Instances:** `Z28061` (Z28061, gobject 7171), `Z28062` (Z28062, gobject 7202)
|
||||
**Template:** `$DARSReactor` · **16 meaningful (UDA) attributes** · 195 total incl. system + config sub-attributes.
|
||||
|
||||
| Attribute | Type | Hist | Alarm |
|
||||
|---|---|---|---|
|
||||
| ChlorineFlow | Integer | ✓ | |
|
||||
| ConfirmTimeoutSec | Integer | | |
|
||||
| Deadband | Double | | |
|
||||
| HeartbeatInterval | Integer | | |
|
||||
| HeartbeatRequest | Boolean | | |
|
||||
| HeartbeatTimeout | Integer | | |
|
||||
| HeartbeatTimeoutAlarm | Boolean | | ✓ |
|
||||
| HydrogenFlow | Integer | ✓ | |
|
||||
| LeakTestMaxDelta | Integer | | |
|
||||
| LeakTestMinDuration | Integer | | |
|
||||
| LeakTestTimeout | Integer | | |
|
||||
| MachineCode | String | | |
|
||||
| MachineDescription | String | | |
|
||||
| MachineID | String | | |
|
||||
| Runtime_Alert | Boolean | | |
|
||||
| TrunkPressure | Float | ✓ | |
|
||||
|
||||
## $DARSReactor.Left — Left_002 / Left_003 (left chamber)
|
||||
|
||||
**Instances:** `Left_002` (Z28061.Left, gobject 7172), `Left_003` (Z28062.Left, gobject 7203)
|
||||
**Template:** `$DARSReactor.Left` · **72 meaningful (UDA) attributes** · 1907 total incl. system + config sub-attributes.
|
||||
|
||||
| Attribute | Type | Hist | Alarm |
|
||||
|---|---|---|---|
|
||||
| AIR_SVC | String | | |
|
||||
| AirAvg | Integer | ✓ | |
|
||||
| AirFlow | Integer | ✓ | |
|
||||
| AirFlowDevAlertPcnt | Float | ✓ | |
|
||||
| AR_SVC | String | | |
|
||||
| ArAvg | Integer | ✓ | |
|
||||
| ArgonFlow | Integer | ✓ | |
|
||||
| ChlorineFlowR | Integer | | |
|
||||
| CL2_SVC | String | | |
|
||||
| Cl2Avg | Integer | ✓ | |
|
||||
| ClFlowDevAlertPcnt | Float | ✓ | |
|
||||
| CoilDiameter | Boolean | ✓ | |
|
||||
| CoilHeight | Integer | ✓ | |
|
||||
| ContainerID | String | ✓ | |
|
||||
| ContainerLoaded | Boolean | ✓ | |
|
||||
| CurrentStep | Integer | | |
|
||||
| CycleEndConfirm | Boolean | | |
|
||||
| CycleEndNotify | Boolean | | |
|
||||
| CycleEndTimeoutAlarm | Boolean | | |
|
||||
| CycleRunning | Boolean | ✓ | |
|
||||
| CycleStartConfirm | Boolean | | |
|
||||
| CycleStartNotify | Boolean | | |
|
||||
| CycleStartTimeoutAlarm | Boolean | | |
|
||||
| Deadband | Double | | |
|
||||
| DelmiaJobStep | Integer | | |
|
||||
| FRR_Reset | Boolean | ✓ | |
|
||||
| FRR_Runtime | Integer | ✓ | |
|
||||
| FRR_Warning | Boolean | ✓ | ✓ |
|
||||
| FurnaceTemp | Integer | ✓ | |
|
||||
| FurnaceTempOverAlarmDev | Integer | ✓ | |
|
||||
| FurnaceTempOverAlertDev | Integer | ✓ | |
|
||||
| FurnaceTempUnderAlarmDev | Integer | ✓ | |
|
||||
| FurnaceTempUnderAlertDev | Integer | ✓ | |
|
||||
| H2_SVC | String | | |
|
||||
| H2Avg | Integer | ✓ | |
|
||||
| HydrogenFlowR | Integer | | |
|
||||
| HyFlowDevAlertPcnt | Float | ✓ | |
|
||||
| MachineBatchID | Integer | | |
|
||||
| MachineBatchWOID | Integer | | |
|
||||
| MachineCycleID | Integer | | |
|
||||
| MantleTemp | Integer | ✓ | |
|
||||
| MoveInReady | Boolean | | |
|
||||
| MoveOutReady | Boolean | | |
|
||||
| MTA_Lockout | Boolean | ✓ | ✓ |
|
||||
| MTA_Reset | Boolean | ✓ | |
|
||||
| MTA_Runtime | Integer | ✓ | |
|
||||
| MTA_Warning | Boolean | ✓ | ✓ |
|
||||
| NumOfParts | Integer | ✓ | |
|
||||
| NumOfTurns | Integer | ✓ | |
|
||||
| OperatorID | String | ✓ | |
|
||||
| PartNumber | String | ✓ | |
|
||||
| PID_Alarm | Boolean | | ✓ |
|
||||
| PID_AlarmString | String | | |
|
||||
| PID_CV | Integer | ✓ | |
|
||||
| PotNumber | String | ✓ | |
|
||||
| PotTempAvg | Integer | ✓ | |
|
||||
| PreviousStep | Integer | | |
|
||||
| ReactorTempAvg | Integer | ✓ | |
|
||||
| RunDuration | Integer | | |
|
||||
| RunEndTime | Time | | |
|
||||
| RunStartTime | Time | | |
|
||||
| SampleCount | Integer | | |
|
||||
| StartingWeight | Integer | ✓ | |
|
||||
| TableSide | Boolean | | |
|
||||
| TableStatus | Integer | | |
|
||||
| TC_Furnace_ID | String | | |
|
||||
| TC_Mantle_ID | String | | |
|
||||
| TC_Spare_ID | String | | |
|
||||
| Vacuum | Float | ✓ | |
|
||||
| VacuumAvg | Float | ✓ | |
|
||||
| VacuumMode | Boolean | ✓ | |
|
||||
| WorkOrder | String | | |
|
||||
|
||||
## $DARSReactor.Right — Right_002 / Right_003 (right chamber)
|
||||
|
||||
**Instances:** `Right_002` (Z28061.Right, gobject 7173), `Right_003` (Z28062.Right, gobject 7204)
|
||||
**Template:** `$DARSReactor.Right` · **72 meaningful (UDA) attributes** · 1907 total incl. system + config sub-attributes.
|
||||
|
||||
| Attribute | Type | Hist | Alarm |
|
||||
|---|---|---|---|
|
||||
| AIR_SVC | String | | |
|
||||
| AirAvg | Integer | ✓ | |
|
||||
| AirFlow | Integer | ✓ | |
|
||||
| AirFlowDevAlertPcnt | Float | ✓ | |
|
||||
| AR_SVC | String | | |
|
||||
| ArAvg | Integer | ✓ | |
|
||||
| ArgonFlow | Integer | ✓ | |
|
||||
| ChlorineFlowR | Integer | | |
|
||||
| CL2_SVC | String | | |
|
||||
| Cl2Avg | Integer | ✓ | |
|
||||
| ClFlowDevAlertPcnt | Float | ✓ | |
|
||||
| CoilDiameter | Boolean | ✓ | |
|
||||
| CoilHeight | Integer | ✓ | |
|
||||
| ContainerID | String | ✓ | |
|
||||
| ContainerLoaded | Boolean | ✓ | |
|
||||
| CurrentStep | Integer | | |
|
||||
| CycleEndConfirm | Boolean | | |
|
||||
| CycleEndNotify | Boolean | | |
|
||||
| CycleEndTimeoutAlarm | Boolean | | |
|
||||
| CycleRunning | Boolean | ✓ | |
|
||||
| CycleStartConfirm | Boolean | | |
|
||||
| CycleStartNotify | Boolean | | |
|
||||
| CycleStartTimeoutAlarm | Boolean | | |
|
||||
| Deadband | Double | | |
|
||||
| DelmiaJobStep | Integer | | |
|
||||
| FRR_Reset | Boolean | ✓ | |
|
||||
| FRR_Runtime | Integer | ✓ | |
|
||||
| FRR_Warning | Boolean | ✓ | ✓ |
|
||||
| FurnaceTemp | Integer | ✓ | |
|
||||
| FurnaceTempOverAlarmDev | Integer | ✓ | |
|
||||
| FurnaceTempOverAlertDev | Integer | ✓ | |
|
||||
| FurnaceTempUnderAlarmDev | Integer | ✓ | |
|
||||
| FurnaceTempUnderAlertDev | Integer | ✓ | |
|
||||
| H2_SVC | String | | |
|
||||
| H2Avg | Integer | ✓ | |
|
||||
| HydrogenFlowR | Integer | | |
|
||||
| HyFlowDevAlertPcnt | Float | ✓ | |
|
||||
| MachineBatchID | Integer | | |
|
||||
| MachineBatchWOID | Integer | | |
|
||||
| MachineCycleID | Integer | | |
|
||||
| MantleTemp | Integer | ✓ | |
|
||||
| MoveInReady | Boolean | | |
|
||||
| MoveOutReady | Boolean | | |
|
||||
| MTA_Lockout | Boolean | ✓ | ✓ |
|
||||
| MTA_Reset | Boolean | ✓ | |
|
||||
| MTA_Runtime | Integer | ✓ | |
|
||||
| MTA_Warning | Boolean | ✓ | ✓ |
|
||||
| NumOfParts | Integer | ✓ | |
|
||||
| NumOfTurns | Integer | ✓ | |
|
||||
| OperatorID | String | ✓ | |
|
||||
| PartNumber | String | ✓ | |
|
||||
| PID_Alarm | Boolean | | ✓ |
|
||||
| PID_AlarmString | String | | |
|
||||
| PID_CV | Integer | ✓ | |
|
||||
| PotNumber | String | ✓ | |
|
||||
| PotTempAvg | Integer | ✓ | |
|
||||
| PreviousStep | Integer | | |
|
||||
| ReactorTempAvg | Integer | ✓ | |
|
||||
| RunDuration | Integer | | |
|
||||
| RunEndTime | Time | | |
|
||||
| RunStartTime | Time | | |
|
||||
| SampleCount | Integer | | |
|
||||
| StartingWeight | Integer | ✓ | |
|
||||
| TableSide | Boolean | | |
|
||||
| TableStatus | Integer | | |
|
||||
| TC_Furnace_ID | String | | |
|
||||
| TC_Mantle_ID | String | | |
|
||||
| TC_Spare_ID | String | | |
|
||||
| Vacuum | Float | ✓ | |
|
||||
| VacuumAvg | Float | ✓ | |
|
||||
| VacuumMode | Boolean | ✓ | |
|
||||
| WorkOrder | String | | |
|
||||
Reference in New Issue
Block a user