Aveva PI
When a new asset is created in PI Asset Framework, auto-populate its metadata attributes from its supplier datasheet PDF using AAS Studio's structured extraction.
Audience: Process engineers + PI AF admins running OT analytics on top of an asset hierarchy that's missing metadata.
Topology
- PI AF onboarding workflow has a "datasheet" attribute that holds a path to the PDF
- Your PowerShell or Python integration script (running on the PI Server or a sidecar) iterates new assets
- For each asset, fetch the PDF, call AAS Studio /api/v1/extract
- Map the extracted Nameplate + TechnicalData fields onto the asset's PI AF attribute template
- Optionally: write the SHA-256 anchor + AAS Studio extraction id back as a custom attribute, so OT engineers can trace any anomaly back to the source datasheet
TypeScript
import { AasStudioClient } from '@aas-studio/sdk'
import { readFileSync } from 'node:fs'
const aas = new AasStudioClient({ apiKey: process.env.AAS_STUDIO_KEY! })
async function populateAssetFromDatasheet(piAssetId: string, pdfPath: string, piClient: PiAfClient) {
const pdf = readFileSync(pdfPath)
const { result } = await aas.extract({ file: pdf, fileName: pdfPath })
const nameplate = result.submodels.find(sm => sm.idShort === 'Nameplate')
const tech = result.submodels.find(sm => sm.idShort === 'TechnicalData')
if (!nameplate || !tech) throw new Error('Required submodels missing')
// Map onto PI AF attributes — names depend on your template
const attrs: Record<string, string> = {
Manufacturer: nameplate.elements.find(e => e.idShort === 'ManufacturerName')?.value ?? '',
Model: nameplate.elements.find(e => e.idShort === 'ManufacturerProductDesignation')?.value ?? '',
SerialNumber: nameplate.elements.find(e => e.idShort === 'SerialNumber')?.value ?? '',
// ... iterate tech.elements onto your numeric attributes
}
await piClient.updateAttributes(piAssetId, attrs)
}Install: npm install @aas-studio/sdk
Python
from aas_studio import AasStudioClient
aas = AasStudioClient(api_key=os.environ["AAS_STUDIO_KEY"])
def populate_asset_from_datasheet(pi_asset_id: str, pdf_path: str, pi_client):
with open(pdf_path, "rb") as f:
response = aas.extract(f.read(), file_name=pdf_path)
submodels = {sm["idShort"]: sm for sm in response["result"]["submodels"]}
nameplate = submodels.get("Nameplate")
tech = submodels.get("TechnicalData")
if not (nameplate and tech):
raise RuntimeError("Required submodels missing")
def find(elements, idShort):
return next((e["value"] for e in elements if e["idShort"] == idShort), "")
pi_client.update_attributes(pi_asset_id, {
"Manufacturer": find(nameplate["elements"], "ManufacturerName"),
"Model": find(nameplate["elements"], "ManufacturerProductDesignation"),
"SerialNumber": find(nameplate["elements"], "SerialNumber"),
# iterate tech["elements"] onto your numeric attributes
})Install: pip install aas-studio
Common pitfalls
- PI AF's attribute names are usually snake_case or PascalCase per your enterprise template. AAS Studio uses IDTA-conformant idShorts (e.g. ManufacturerProductDesignation). Build a static mapping table once — don't try to fuzzy-match.
- Range elements (operating temperature, voltage range) need two PI AF attributes — min and max — or a Composite type. Plan the attribute template with this in mind.
- For high-volume new-asset onboarding, hit the AAS Studio Team plan (300 extractions/month, €99/mo). The Free plan's 3/month limit gets exhausted in a single afternoon of onboarding.