Files
ScadaBridge/docs/former-api-specs/dnc/Delmia-Integration-API.md
T
Joseph Doherty 8a78e759c0 docs: former-api-specs (MES + DNC/Delmia) + inbound compile-error known issue
- former-api-specs/mes: Alarm-API, MoveIn-MoveOut-API, API-key authgaps (from ~/Desktop/mesapi)
- former-api-specs/dnc: Delmia-Integration-API — Delmia document service + WW recipe-download notify (from ~/Desktop/delmiaintegration)
- known-issues: inbound API compile error not client-visible; no api-method validate
2026-06-26 04:13:19 -04:00

11 KiB

Delmia / DNC Integration API — document download & WW recipe-download notification

Reference for the delmiaintegration solution (~/Desktop/delmiaintegration), the legacy bridge that pulls "proven" manufacturing documents (NC programs / recipes) out of DELMIA Apriso and notifies AVEVA Wonderware that a recipe was downloaded for a machine. The recipe/NC-program push to machines is classic DNC (Distributed Numerical Control), hence this lives under former-api-specs/dnc/.

There are two distinct API surfaces in this solution:

# Surface Direction Transport
A Delmia document web service integration → Delmia (consumed) form-urlencoded POST, XML response
B WW recipe-download notification WWNotifier CLI → Wonderware receiver JSON POST (/notify)

Surface B is the legacy predecessor of the ScadaBridge DelmiaRecipeDownload inbound method — same field set and result shape (see ScadaBridge equivalent below).

Source files (under ~/Desktop/delmiaintegration):

  • DelmiaIntegration/DelmiaClient.cs — Delmia HTTP client (Surface A)
  • DelmiaContracts/*.cs — XML contracts (DownloadResult, SearchResults/SearchResult, + unused MachineInfo/MachineSearchResults/UserInfo)
  • WWNotifier/Program.cs, WWNotifier/CommandLineOptions.cs, WWNotifier/Models/RecipeDownload*.cs — the CLI notifier (Surface B)
  • WWNotifier/App.configNotifyURL / NotifyTimeout

End-to-end flow

DELMIA Apriso  ──(A) RequestProvenDocument / RequestDocument / Search──►  DelmiaClient
   (intercim "ruleset" web service, XML)                                    │ downloads proven doc/recipe to a path
                                                                            ▼
                                          WWNotifier.exe  ──(B) POST /notify {RecipeDownload}──►  Wonderware "WW receiver"
                                          (CLI, exit code + YES/NO)         ◄── {RecipeDownloadResult} ──

Surface A — Delmia document web service (consumed by DelmiaClient)

DelmiaClient (DelmiaClient.cs) is a thin HttpClient wrapper. The base URL is supplied by the caller (constructor / URL property — there is no default in DelmiaIntegration/App.config); Timeout defaults to 30 s. Every call is an application/x-www-form-urlencoded POST to {URL}/<Operation>, and every response is XML deserialized with XmlSerializer (root namespace http://intercim.com/ruleset — the Apriso/InterCIM heritage).

Verb Path Form fields Response (XML) Client method
POST {URL}/RequestProvenDocument username, machineID, partNumber, operationNumber, workOrderNumber DownloadResult RequestProvenDocument[Async]
POST {URL}/RequestDocument + documentKey DownloadResult RequestDocument[Async]
POST {URL}/Search username, machineID, partNumber, operationNumber SearchResults Search[Async]
  • RequestProvenDocument — fetch the single proven (released/approved) document for the part + operation, logging it against username / workOrderNumber.
  • Search — list candidate documents matching the part/operation (each carries a DocumentKey + DocumentURL).
  • RequestDocument — fetch one specific document chosen from a search by documentKey.

username here is identity/audit only — it is a form field, not an authentication credential. There is no API key, no Authorization header, no TLS requirement on this surface (see gotchas).

Response — DownloadResult (metadata about the download)

DownloadResult describes who/what/which order+document was downloaded — it does not carry the file bytes (the file lands at a download path on the Delmia side). Fields:

Group Fields
User UserKey (int), UserName, UserSite
Machine MachineKey (int), MachineID, MachineSite
Order WorkOrderNumber, ShopOrderKey (int), ShopOrderID, ShopOrderStatus, ShopOrderOperKey (int), ShopOrderOperID, ShopOrderOperStatus
Document DocumentKey (int), DocumentName, DocumentRev, DocumentStatus
Part PartID, PartRev
Outcome TransferSuccessful (bool), ErrorMessage (string)

Success is TransferSuccessful, not the HTTP status. Treat TransferSuccessful == true as the only success signal; ErrorMessage carries the reason otherwise.

Response — SearchResults / SearchResult

SearchResults = { List<SearchResult> Results; string ErrorMessage }. Each SearchResult: ShopOrderKey/ShopOrderID/ShopOrderStatus, ShopOrderOperKey/ShopOrderOperID/ShopOrderOperStatus, DocumentKey (int), DocumentObjectID (int, with an XmlIgnore …Specified flag), DocumentName, DocumentRev, DocumentStatus, DocumentURL, PartID, PartRev.

Quick reference (curl, Surface A)

# Search for candidate documents (values from DownloadTestUtil's example)
curl -X POST "{URL}/Search" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "username=dohertj2" \
  --data-urlencode "machineID=000005" \
  --data-urlencode "partNumber=00444455599" \
  --data-urlencode "operationNumber=0100"
# -> <SearchResults xmlns="http://intercim.com/ruleset"> … </SearchResults>

# Request the proven document for that part/operation
curl -X POST "{URL}/RequestProvenDocument" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "username=dohertj2" \
  --data-urlencode "machineID=000005" \
  --data-urlencode "partNumber=00444455599" \
  --data-urlencode "operationNumber=0100" \
  --data-urlencode "workOrderNumber=W111111"

Surface B — WW recipe-download notification (WWNotifier → WW receiver)

WWNotifier.exe (WWNotifier/Program.cs) is a command-line tool invoked by the download process to tell Wonderware that a recipe/NC file was placed at a path for a machine. It POSTs a JSON RecipeDownload to the configured receiver and interprets the JSON RecipeDownloadResult.

CLI options (CommandLineOptions)

Short Long Required Meaning
-d --downloadpath yes File download path
-m --machine yes Machine code
-w --workorder yes Work order number
-p --partnumber yes Part / item number
-s --seqop no Job step / sequence number
-u --username no Operator username

Endpoint & payload

POST {NotifyURL} with a JSON body, expecting a JSON reply. From WWNotifier/App.config: NotifyURL = http://wonder-app-vd01.zmr.zimmer.com:9001/notify, NotifyTimeout = 30 (seconds). NotifyURL may be a comma-separated list — each is tried in order and the first success wins (failover).

Request — RecipeDownload (JSON)

Field Type Source
MachineCode string --machine
DownloadPath string --downloadpath
WorkOrderNumber string --workorder
PartNumber string --partnumber
JobStepNumber string --seqop
Username string --username

Response — RecipeDownloadResult (JSON): { "Result": bool, "ResultText": string }.

Process contract (stdout + exit code)

The caller (Delmia) reads WWNotifier's console output and exit code:

  • On success → prints YES; exit code 0.
  • On any failure (arg parse, missing config, all receivers failed, Result == false) → prints NO plus a reason line; Environment.ExitCode = -1.
WWNotifier.exe -m Z28061 -d "C:\recipes\wo111111.nc" -w W111111 -p P111111 -s 0100 -u chamalas
# stdout: YES        (or: NO\n<reason>)
# POSTs {"MachineCode":"Z28061","DownloadPath":"C:\\recipes\\wo111111.nc", … } to /notify

Other contracts (defined but unused)

MachineInfo, MachineSearchResults ({ List<MachineInfo> Results; string ErrorMessage }), and UserInfo exist in DelmiaContracts (same intercim.com/ruleset namespace) but are not wired to any DelmiaClient operation — scaffolding for machine-lookup / user-lookup endpoints that were never implemented. Shapes, for reference: MachineInfo = MachineKey/MachineID/MachineName/ DownloadPath/MachineDescription/MachineSite/MachineStatus; UserInfo = UserKey/UserName/ UserSite/IsActive.


Behavior notes & gotchas

  • No authentication on either surface. Surface A's username is just a logged form field; Surface B sends no credential at all. Both are plaintext HTTP. (Contrast the ScadaBridge inbound API, which requires X-API-Key/Bearer — see ../mes/authgaps.md.)
  • Surface A ignores HTTP status. DelmiaClient never calls EnsureSuccessStatusCode; a non-2xx body is handed straight to XmlSerializer, which typically throws → the catch returns a generic TransferSuccessful = false / "Failed to call Delmia web service at '<URL>'.". The real HTTP error is lost.
  • Sync methods block on .Result. RequestProvenDocument/RequestDocument/Search call .Result on the async POST (deadlock-prone in some contexts); async variants exist.
  • WWNotifier has a latent NPE in its error path. On a notify exception it logs error.InnerException.Message (Program.cs:129); if InnerException is null this throws inside the catch, masking the original error.
  • NotifyURL failover is first-success-wins, in list order; a slow first endpoint costs up to NotifyTimeout before the next is tried.
  • Surface A base URL is caller-supplied (no config default), so the effective Delmia endpoint depends on whoever constructs DelmiaClient (e.g. TestUI/DelmiaClientUI).

ScadaBridge equivalent (porting note)

  • Surface B → ScadaBridge Inbound API DelmiaRecipeDownload. The legacy WWNotifier.exe + the /notify WW receiver are replaced by POST /api/DelmiaRecipeDownload (authenticated with X-API-Key/Bearer). The contract is identical: request { MachineCode, DownloadPath, WorkOrderNumber, PartNumber, JobStepNumber, Username } → response { Result, ResultText }. The inbound script routes to the site via Route.To(MachineCode).Call("ProcessRecipeDownload", …). The CLI's comma-list failover is superseded by Traefik active-node routing; the YES/NO + exit code contract becomes the HTTP status + JSON body.
  • Surface A (Delmia document service) has no direct ScadaBridge equivalent — retrieving proven documents from DELMIA Apriso remains an external concern (it would be an External System Gateway call if pulled into ScadaBridge).

This file documents the legacy delmiaintegration contracts for reference/parity during that migration.