DPM/HTTP¶
The primary backend. Uses a custom binary protocol ("PC" format) over TCP.
sequenceDiagram
participant App as Your App
participant Proxy as acsys-proxy<br>:6802
participant DPM as DPM Server
App->>Proxy: TCP connect
App->>Proxy: HTTP handshake
Proxy->>DPM: Forward connection
DPM-->>App: OpenList_reply (list_id)
App->>DPM: AddToList (device)
DPM-->>App: DeviceInfo_reply
App->>DPM: StartList
loop Streaming
DPM-->>App: Scalar_reply / Array_reply
end
App->>DPM: StopList
Characteristics¶
- Connection pooling: Multiple reads share pooled connections
- Independent subscriptions: Each
subscribe()creates its own TCP connection - Kerberos auth: Required for writes, optional for reads
- Heartbeats: Server sends
ListStatus_replyevery ~2 seconds
Usage¶
import pacsys
# Read-only (uses global backend)
value = pacsys.read("M:OUTTMP")
# Explicit backend
with pacsys.dpm() as backend:
value = backend.read("M:OUTTMP")
# With authentication for writes
from pacsys import KerberosAuth
with pacsys.dpm(auth=KerberosAuth(), role="testing") as backend:
result = backend.write("M:OUTTMP", 72.5)
Write Permissions (Kerberos)¶
When you call write(), the DPM server checks whether your Kerberos identity is allowed to set the target device. The server uses two authorization paths, tried in order:
Path 1 - Role + device allowlist. The server looks up your Kerberos principal in the DB, checks that you have the requested role (e.g. "testing"), then checks that the target device is allowed for that role.
Path 2 - Console class bitmask (fallback). Only executed if role check fails. Each console user has a classes bitmask (e.g. MCR, ASTA, ...) and each device has a protection_mask. If user.classes & device.protection_mask > 0 (i.e. values overlap on at least 1 bit), the write is allowed.
Configuration¶
| Parameter | Default | Environment Variable |
|---|---|---|
host |
acsys-proxy.fnal.gov | PACSYS_DPM_HOST* |
port |
6802 | PACSYS_DPM_PORT* |
pool_size |
4 | PACSYS_POOL_SIZE* |
*Environment variables only affect the global (implicit) backend used by pacsys.read() etc. The pacsys.dpm() factory uses parameters passed directly.