Live streams
Collector: OPC DA
Read an OPC DA (Classic) server on Windows, for example next to the PI Interface for OPC DA.
OPC DA (Classic)
Reads an OPC DA 2.05a or 3.0 server (OPC Classic, COM) at the rate the server offers, with each value's own quality and timestamp. Use it where the control system has no OPC UA server, typically where PI collects through the PI Interface for OPC DA: the collector becomes a second client of the same DA server, next to PI. If the DCS also offers OPC UA, use the OPC UA source instead.
Install on the DA host
- Check that the OPC Core Components (OPC Foundation, x86-x64 redistributable) are installed. They are wherever a DA server or the PI Interface for OPC DA runs: look for OPC Core Components Redistributable in Programs and Features. If not, install the x86-x64 MSI from the OPC Foundation (MIT licence). The OPC Foundation no longer maintains them; they come with your DA server, Kymoscope does not ship them.
- Install Python 3.10 to 3.13 (64-bit, from python.org) and the collector with the OPC DA extra:
pip install "kymoscope-collector[opcda,windows]". This adds comtypes (MIT), pure Python: no DLL or EXE of ours to approve. - Find the server's ProgID (the DA server's documentation, the PI interface's
/server=start-up parameter, or any OPC browser on the host). - Write the tag list (below), run
kymoscope-collector discoverto check it, then install the Windows service. Run the service under the same kind of account the PI interface uses, so the DA server's DCOM permissions already let it in.
sources:
- name: Customer A DCS
type: opcda
server: Vendor.OPCServer.1 # ProgID, or the CLSID as {xxxxxxxx-...}
tags: tags.csv # leave out to collect every item of the server (not advised)
# host: dcs-opc01 # remote DCOM, best effort; leave out to run on the DA host (advised)
# mode: poll # cache reads instead of callbacks (no inbound port)| Key | Meaning |
|---|---|
server | Required. The DA server’s ProgID (e.g. Vendor.OPCServer.1) or its CLSID in braces. |
tags | Path to tags.csv, relative to collector.yaml. Left out: every item in the server’s address space is collected. That can be tens of thousands of items and DA servers often licence clients or items, so set a list. |
mode | subscribe (default): the server calls back with changes (IOPCDataCallback). poll: the collector reads the server’s cache at each group’s rate (IOPCSyncIO, never from the device, so the DCS is not loaded); needs no callback into the collector host. |
host | Empty (default): the server on this host. A host name: remote DCOM, best effort (see below). |
default_sampling_ms | 1000. The rate for a tag that has no sampling_ms in tags.csv and no scan-rate property on the server. |
timeout_s | 30. The longest any single call to the server may take before the collector reconnects. |
browse_timeout_s | 300. The same for browsing the address space (no tags list), which can take minutes on a large server. |
tags.csv
The same file as for OPC UA, with node_id written da:<ItemID>: the server's fully qualified ItemID (for example FIC101.PV). An empty name takes the ItemID. An empty unit or description takes the item's engineering-unit and description properties from the server. The rate is sampling_ms, else the item's scan-rate property, else default_sampling_ms; tags with similar rates share one DA group. Enumerated items (EU type 2) keep their labels. The file is re-read when it changes, as for OPC UA.
node_id,name,group,sampling_ms,unit,description
da:FIC101.PV,FIC-101,,,m3/h,Feed flow
da:Unit1.TIC201.PV,TIC-201,,1000,degC,Reactor temperaturekymoscope-collector discover --config collector.yaml --source "Customer A DCS" --out tags.csv writes the configured tags with the server's units, descriptions and rates. With no tags key it browses the server's whole address space (flat or hierarchical) and writes every item: delete the rows you do not want, then set tags: tags.csv. OPC DA has no history here, so backfill does not apply.
Seeding the list from PI
At a PI site the quickest list is PI's own: the PI Interface for OPC DA maps each PI point to an ItemID in its InstrumentTag attribute. Export the interface's points with PI Builder (filter on its point source) to CSV, then convert:
Selected(x),Tag,PointSource,InstrumentTag,EngUnits,Descriptor,Location4
,FIC-101,OPC,FIC101.PV,m3/h,Feed flow,1
,TIC-201,OPC,Unit1.TIC201.PV,degC,Reactor temperature,2python -m kymoscope_collector.opcda_source from-pi points.csv --out tags.csv --scan-class 1=1000 --scan-class 2=5000node_id=da:+ InstrumentTag,name= the PI tag (columnTagorName),unit= EngUnits,description= Descriptor. Operators see the same names as in PI Vision.Location4(the PI scan class) goes togroup.--scan-class N=MSgives that class's period (the interface's/f=parameters) assampling_ms; without it the server's scan rate is used.- Points with an empty InstrumentTag (where the interface takes the ItemID from ExDesc) are skipped and counted. Add them by hand.
Quality and time
Each value keeps the server's timestamp (a missing one gets the collector's time and is counted in server_time_fallback). DA quality becomes the matching OPC UA status: Good and Good local override are values, the Uncertain sub-statuses are values marked uncertain, and every Bad quality (not connected, device or sensor failure, comm failure, last known value, out of service, waiting for initial data) is stored as a gap with its status. Arrays and strings are not channels and are dropped.
Remote DCOM
Only if the collector cannot run on the DA host or the PI interface node. Set host and expect work with the site's Windows team:
- Since the DCOM hardening of March 2023 (KB5004442) the server must accept packet-integrity authentication. The collector asks for it; old servers that cannot fail (events 10036/10037/10038).
- DCOM needs TCP 135 and the dynamic RPC ports, and in
subscribemode the server calls back into the collector host: an inbound port.mode: pollavoids the callback. - Both hosts in the same domain (or matching local accounts), DCOM launch and access rights for the collector's account on the server.
- A ProgID is looked up on the remote host through its OPCEnum service (part of the OPC Core Components). If OPCEnum is not installed or not reachable there, set
serverto the CLSID instead: the default value ofHKEY_CLASSES_ROOT\<ProgID>\CLSIDon the DA host.
If neither is acceptable, an OPC DA to OPC UA wrapper on the DA host (Kepware, Matrikon UA Tunneller and similar) and the OPC UA source is the supported alternative.
Health and troubleshooting
| Health channel | Meaning |
|---|---|
connected | 1 while connected to the server. |
values_per_s | Values received per second (5-second average). |
revised | Tags in groups whose update rate the server changed from the one asked for. |
bad_items | ItemIDs the server rejected (the log names them and the error code). |
quality_good / quality_uncertain / quality_bad | Values received per quality class since start. |
server_state | The server’s own state: 1 running; anything else makes the collector reconnect. |
reconnects, clock_offset_s, server_time_fallback | As for OPC UA. In poll mode also polls, poll_errors, overruns. |
threads_abandoned / threads_hung | (Also reported as com_threads_abandoned / com_threads_hung until the next release.) Calls to the server that outlasted timeout_s, and how many of them are still stuck. Each source has its own COM thread, so one stuck server never holds up another; the stuck thread is set aside and the source reconnects on a new one. With 3 still stuck it waits (up to 10 minutes) before trying again. |
- "OPC DA uses Windows COM" at start-up: the config is on Linux or Docker; OPC DA needs the Windows host.
- Invalid class string / class not registered: the ProgID is wrong or the server is not installed on this host.
- Cannot resolve the ProgID … through its OPCEnum: a remote
hostwithout a reachable OPCEnum. Setserverto the CLSID (see Remote DCOM). - Access denied (0x80070005): the service account has no DCOM launch or access right on the DA server. Use the account the PI interface runs as, or ask for the rights in dcomcnfg.
- Interface not registered / no such interface: the OPC Core Components are missing or only the 32-bit half is installed. Install the x86-x64 redistributable.
- Rejected by the server: 0xC0040007 (unknown ItemID) or 0xC0040008(bad ItemID syntax): check the ItemID in an OPC browser; the other tags keep running.
- No values in subscribe mode, but poll works: the server cannot call back into the collector (remote DCOM or a firewall). Run on the DA host, or use
mode: poll. - The server restarts or shuts down: the collector notices (shutdown notice or the 10-second status check) and reconnects by itself, backing off from 1 to 60 seconds.