# AVEVA PI

> Reference for the AVEVA PI driver: PI Web API over HTTPS, bearer or Basic authentication, AF and PI point addressing, reads and writes.

The AVEVA PI driver reads and writes an **AVEVA PI System** through **PI Web API**,
the system's REST interface (JSON over HTTP). It is a client-mode driver — **Ganter
Lab connects to the PI Web API service** — and the transport is **HTTPS by
default**: the driver puts the device's credentials on every request it makes, so
an unencrypted connection would publish them. Plain HTTP exists only as an explicit
per-device choice.

A tag addresses one **AF attribute**, one **PI point**, or a raw PI Web API stream,
and reads its snapshot (current) value.

## Connection fields {#connection-fields}

| Field | What it is | Format | Default |
|---|---|---|---|
| Host | The PI Web API server's host name or IP address. | Host name or IP | empty |
| Port | The TCP port of the service. Zero means the driver default, 443. | port number | 0 (= 443) |
| Resource path | The service root path appended to the authority. Blank, or a bare `/`, means PI Web API's standard root, `piwebapi`. Any other path is the path the driver opens, exactly as typed: a service published behind a reverse proxy on `/pi` is reached at `/pi`, and nothing is appended to it. Write the whole path a browser would need, `piwebapi` included where the service still answers there. | path text | blank (= `piwebapi`) |
| Send over plain HTTP | Steps this one device down from HTTPS to clear HTTP. Off means HTTPS, the normal PI Web API transport. The panel states the consequence: on plain HTTP the bearer token or password is sent unencrypted on every request. Use it only for a PI Web API that answers on no other transport. | on / off | off |
| Username | Account for **HTTP Basic** authentication, used only when no bearer token is set. Empty (with no token) leaves the requests anonymous. | Free text | empty |
| Password | The password paired with the username. Protected at rest per Windows user; a secret entered under another Windows account shows as unreadable and must be re-entered. | Free text | empty |
| Bearer token | A token sent as `Authorization: Bearer …` on every request. When set it **wins over** the username/password pair. Protected at rest the same way. | Token text | empty |

On connect the driver verifies the service root (HEAD, falling back to GET). Over
HTTPS, the service's TLS certificate must pass normal Windows certificate
validation. The poll interval is configurable: the device default (1000 ms) applies
to every tag that does not state its own.

## Tag addressing {#tag-addressing}

The tag's **PI path** field accepts four forms:

| Form | Looks like | How it is resolved |
|---|---|---|
| AF attribute path | `\\AFServer\Database\Element\SubElement\|Attribute` | Looked up once through `attributes?path=…` to obtain the attribute's WebId |
| PI point path | `\\PIServer\TagName` | Looked up once through `points?path=…` to obtain the point's WebId |
| WebId | The opaque WebId string itself | Used directly (recognized as a long token with no `\`, `\|` or `/`) |
| Relative URL | `streams/{webId}/value`, `streamsets/…`, `attributes?…`, `points?…` | Sent as-is under the service root |

Path lookups are cached for 12 hours, so steady-state polling does not repeat
them. For the first three forms the read GETs the stream's **snapshot value**
(`streams/{webId}/value`) and extracts the JSON `Value` field; a relative URL is
read literally, so point it at an endpoint that answers with a value document. The
result is converted to the tag's declared data type.

The archive's own verdict on the sample is read with it. A value the archive marks
as **not good**, as **questionable**, or as **substituted** (a number entered by
hand rather than measured) is not a reading of the equipment, so it is not
published as one: the tag goes to bad quality and the reason says which of the
three it was. The same happens when the response carries no value, or answers with
a digital state rather than a single value, in which case the state's name is part
of the reason. Nothing is invented in their place, and no document arrives as if it
were the measurement.

Examples:

- `\\PI-SRV01\FURNACE.TEMP` — a classic PI point.
- `\\AF-SRV\Plant\Line 3\Furnace|Temperature` — an AF attribute.
- `streams/F1DPmNQx2kqBk0qbIVMoxAVBJw/value` — a raw stream URL, useful when you
  already hold the WebId from another tool.

## Writes {#writes}

Tags with a writable access mode write through PI Web API's stream endpoint: a
POST of `{"Timestamp":"*","Value":…}` (timestamp `*` means now) to
`streams/{webId}/value`. The write needs a resolvable WebId, so it works for tags
addressed by AF path, PI point path, WebId, and by a relative `streams/…` URL as
well: the WebId is read out of that URL and the write lands on that stream's value
endpoint, whatever read-side sub-resource (`recorded`, say) the address carried past
it. Three relative forms are refused, because each answers with a document rather
than with one stream's value and a write would address the wrong resource:
`streamsets/…`, `attributes?…` and `points?…`. The refusal names the accepted forms.
Whether the write lands also depends on the PI Web API being configured for writes
and the account having write access to the point.

The value you type in the tag's write box is the engineering value; the tag's
conversion stages are reversed before the raw value goes on the wire, as described
on the [Connector](connector) page.

## Supported data types {#supported-data-types}

Boolean, Int32, Int64, Float, Double and String. Numeric PI points are typically
Float or Double. A digital state is not a single value, so a point that answers with
one reads as bad quality naming the state, whatever type the tag declares.

## Commands {#commands}

Beyond reading and writing points, a PI Web API endpoint can be asked to do something, and
which requests it accepts is the service's own business. Declare each one on the device, in
the **Commands** card of its page: a name, the relative URL it is POSTed to under the
service root, and optionally the name of the one value it takes, which travels as the
request body. The row's Run verb sends it and reports what the service answered; the command
also becomes a method on the device in this station's own OPC UA address space.

## Discovery {#discovery}

The **Discover** button reads one service. Put its address and the AF element the walk
starts from in the driver page's Scan scope card, separated by a `#`:
`https://pi-host/piwebapi#\\AF-SRV\Plant\Line 3`. The scan resolves that element, walks
every element under it, and offers the device with one point per attribute, each addressed
by its own stream. The scan reads the service without credentials, because it runs before
the device that would hold them exists, so a PI Web API that authenticates every request
answers nothing and the device is added by hand instead: add the service by host and add
tags by their AF or PI paths, as the add-a-device flow on the [Connector](connector) page
describes.
