# LumiScan Keryx 1.0.0.7 – complete documentation

> All pages of the LumiScan Keryx 1.0.0.7 manual (language: en) by HD Vision Systems GmbH, in navigation order. Each page starts with a level-1 heading followed by its URL; cite that URL. Manual: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/

# LumiScan Keryx

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/index.html

|   |   |   |
| --- | --- | --- |
| ![Three LumiScan apps connected to LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/_images/intro/step-1.svg)<br><br>**Every app publishes its nodes.** Values, functions and results go into one tree. | ![Node tree with the address of the capture function highlighted](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/_images/intro/step-2.svg)<br><br>**One address for everything.** The same addresses on ctrlX OS and on a PC. | ![PLC, SCADA and a program connected over OPC UA](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/_images/intro/step-3.svg)<br><br>**Your PLC calls it directly.** Over OPC UA, from SCADA or from your own program. |

LumiScan Keryx is the data backbone of the LumiScan apps. Every app puts its values, functions and results into one tree of named, typed nodes, and PLCs, SCADA systems, test scripts and your own programs reach all of them at one address, with no point-to-point wiring. On a PC with Windows 11 or Ubuntu 24.04 Keryx provides the Data Layer; on ctrlX OS the apps use the ctrlX Data Layer with the same addresses and call patterns.

The LumiScan vision apps - Cam Driver, AI Object Matching, Calibration, the finders and the code readers - offer their functions as **nodes of a Data Layer**. A PLC, an OPC UA client or your own program reads, writes and calls these nodes, and the apps use the same nodes to pass images and results to each other. LumiScan Cockpit reads them to show images and results.

This manual describes what is the same in every app: how addresses are built, the three ways to call a function, streams, status codes, settings and the tools. Each product manual describes only its own nodes, in its **Data Layer Reference**, and links here for the rest.

## One interface, two Data Layers

| The app runs on | Data Layer | Read |
| --- | --- | --- |
| ctrlX OS (ctrlX CORE or a ctrlX IPC) | ctrlX Data Layer | [ctrlX Data Layer on ctrlX OS](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/ctrlx-data-layer.html) |
| a PC with Windows 11 or Ubuntu 24.04 | LumiScan Keryx | [LumiScan Keryx on a PC](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html) |

**The node addresses, the node types and the call patterns are the same on both.** A program written against one works against the other; only the connection, the tools and the names of a few results differ. See [ctrlX Data Layer and LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/platforms.html).

> [!NOTE]
> This manual describes the Data Layer interface of the upcoming releases of the vision apps. Several nodes have moved compared with earlier releases, without an alias at the old address. If a program written for an earlier release reads a node that is "not found", compare it with the **Data Layer Reference** of the app version you run.

## Start here

New to Keryx? Start with [What Is LumiScan Keryx?](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/what-is-keryx.html) and try it hands-on in [Getting Started with LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/getting-started.html). Then:

1. Read [Addresses and Modules](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/addresses.html) to understand where an app’s nodes are.
2. Choose how to call a function: [Choosing a Pattern](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/calling-functions.html).
3. Look up the nodes of your app in its manual’s **Data Layer Reference**.
4. On a PC, set up the broker as in [LumiScan Keryx on a PC](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html). To connect a PLC or SCADA system there, use the [OPC UA Connector](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/opc-ua.html).
5. On ctrlX OS, read [ctrlX Data Layer on ctrlX OS](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/ctrlx-data-layer.html): there is nothing to set up, and a ctrlX PLC on the same device uses the nodes directly.

Quick answers: [Data Layer FAQ](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/faq.html). Something does not work: [Troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html).

## The apps on the Data Layer

| App | Base address |
| --- | --- |
| [LumiScan Cam Driver](https://docs.hdvisionsystems.com/en/lumiscan-cam-driver/latest/index.html) | `hdvisionsystems/lumiscan-cam-driver` |
| [LumiScan AI Object Matching](https://docs.hdvisionsystems.com/en/lumiscan-ai-object-matching/latest/index.html) | `hdvisionsystems/lumiscan-ai-object-matching` |
| [LumiScan Calibration](https://docs.hdvisionsystems.com/en/lumiscan-calibration/latest/index.html) | `hdvisionsystems/lumiscan-calibration` |
| [LumiScan Template Finder](https://docs.hdvisionsystems.com/en/lumiscan-template-finder/latest/index.html) | `hdvisionsystems/lumiscan-template-finder` |
| [LumiScan Object Finder](https://docs.hdvisionsystems.com/en/lumiscan-object-finder/latest/index.html) | `hdvisionsystems/lumiscan-object-finder` |
| [LumiScan Area Detector](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/latest/index.html) | `hdvisionsystems/lumiscan-area-detector` |
| [LumiScan Text Reader](https://docs.hdvisionsystems.com/en/lumiscan-text-reader/latest/index.html) | `hdvisionsystems/lumiscan-text-reader` |
| [LumiScan DMC Reader](https://docs.hdvisionsystems.com/en/lumiscan-dmc-reader/latest/index.html) | `hdvisionsystems/lumiscan-dmc-reader` |
| [LumiScan QR Code Reader](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/latest/index.html) | `hdvisionsystems/lumiscan-qr-code-reader` |
| [LumiScan Aztec Code Reader](https://docs.hdvisionsystems.com/en/lumiscan-aztec-code-reader/latest/index.html) | `hdvisionsystems/lumiscan-aztec-code-reader` |
| [LumiScan Barcode Reader](https://docs.hdvisionsystems.com/en/lumiscan-barcode-reader/latest/index.html) | `hdvisionsystems/lumiscan-barcode-reader` |
| [LumiScan Cockpit](https://docs.hdvisionsystems.com/en/lumiscan-cockpit/latest/index.html) | none: Cockpit only reads the other apps' nodes |

Licensing is described in the [LumiScan Licensing](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/index.html) manual.

# What Is LumiScan Keryx?

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/what-is-keryx.html

**LumiScan Keryx** is the data backbone of the LumiScan vision apps. Every app puts its values, functions and results into **one tree of named nodes**, and everything else - a PLC, a SCADA system, your own program, a test script, the people commissioning the cell - reaches them at **one address**. Nothing is wired point to point.

The name comes from the Greek *kēryx*, the herald: the messenger who carries news between the parties.

**LumiScan Keryx connects the apps that provide data with everyone who uses it**

```mermaid
%% LumiScan Keryx - concept. Rendered by Mermaid in the browser; edit and preview at https://mermaid.live
flowchart LR
  subgraph users["Who uses the data: read · write · call · subscribe"]
    plc["`**PLC or SCADA**
    through the OPC UA Connector`"]
    prog["`**Your program**
    C++, Python or OPC UA`"]
    tests["`**Scripts and tests**
    krxclient`"]
    people["`**People**
    Keryx page, Cockpit`"]
  end
  keryx["`**LumiScan Keryx**
  the broker, one address for all:
  tcp://127.0.0.1:5555

  one tree of named, typed nodes:
  hdvisionsystems/lumiscan-cam-driver/camera1/...`"]
  subgraph apps["Who provides it: register nodes · publish"]
    cam["`**Cam Driver**
    camera images`"]
    ai["`**AI Object Matching**
    neural networks`"]
    find["`**Finders and readers**
    parts, codes, text`"]
    calib["`**Calibration**
    pixels to 3D`"]
    own["`**Your own function**
    C++ or Python`"]
  end
  plc & prog & tests & people <--> keryx
  keryx <--> cam & ai & find & calib & own
  class keryx key
  classDef key fill:#faf6dc,stroke:#a8961f,color:#1f2328
```

## Why Keryx {#why}

In a vision project, the image processing is only part of the work. The rest is getting it into the machine: a handshake with the PLC, a result format the PLC can read, a live view, a way to find out why a part was rejected, and tests without the real line. Without a common backbone this is built again for every project and every customer.

Keryx does this work once, for all LumiScan apps:

- every app offers its functions in the same way, at addresses built by the same rules;
- a PLC, a program or a person uses all apps through one connection;
- adding a second camera or another app means adding one more participant, not rewiring the cell.

## The concept {#concept}

### One tree of nodes {#nodes}

Everything on Keryx is a **node** with an **address**, written like a file path:

```none
hdvisionsystems/lumiscan-cam-driver/camera1/control/capture/execute
```

A node is a value (a number, a flag, a text, an image), a function you can call, or a folder that groups other nodes. Every node **describes itself**: what it is, its type, and whether it may be read, written, called or subscribed to. So a client can browse the tree and find out what an app offers without a separate interface description - in the same way as an OPC UA server.

The addresses follow one scheme in every app: `<app>/<module>/control/…` for the functions, `input/…` for what you write before a call, `output/…` for the results. See [Addresses and Modules](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/addresses.html).

### Providers, clients and the broker {#participants}

| Role | What it does |
| --- | --- |
| **Provider** | an app that serves nodes: it registers them and publishes changes. The Cam Driver, AI Object Matching, the finders, the readers and Calibration are providers. |
| **Client** | anyone who reads, writes, calls or subscribes: a PLC, your program, `krxclient`, the Keryx page, Cockpit - and an app that uses another app’s results. |
| **Broker** | the one program everybody connects to (`krxsystem`). It holds the tree and routes every request to the provider of the node. On a PC there is one broker, at `tcp://127.0.0.1:5555`; the first app that needs it starts it, and the apps start it again if it stops. |
| **Gateway** | a client that makes the tree available over another protocol. The [OPC UA Connector](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/opc-ua.html) shows the whole tree as an OPC UA server, so that any PLC or SCADA system with an OPC UA client can use the apps. |

### Three ways to call a function {#patterns}

How a function is called depends on how long it takes:

| Pattern | Use it for |
| --- | --- |
| [Execute](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/execute.html) | work that is done within about a second: one write, answered when the work is finished. Example: take an image. |
| [Handshake](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/handshake.html) | work that can take longer: the client sets `request`, the app answers through `ready` - the pattern every PLC programmer knows. Example: connect a camera. |
| [Stream](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html) (experimental) | continuous work: subscribe once and receive every result. Example: every camera frame goes to AI Object Matching, and every detection to your program. |

Most functions of the Cam Driver, AI Object Matching and Calibration are offered in more than one pattern, with one implementation behind them: the result is the same. See [Choosing a Pattern](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/calling-functions.html).

### The same on ctrlX OS and on a PC {#platforms}

On a PC with Windows 11 or Ubuntu 24.04 the apps use the Keryx broker. On ctrlX OS they use the ctrlX Data Layer instead. The **addresses, types and call patterns are the same** on both, so a PLC program or an application written for one works with the other. See [ctrlX Data Layer and LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/platforms.html).

## What it gives you {#benefits}

### Decision makers and project leads {#benefits-decision-makers}

- **Less engineering per project.** The connection to PLC, live view and test tools is part of the product, not built again for every cell.
- **Standard interfaces, no lock-in.** Keryx follows the interface of the ctrlX Data Layer; towards the machine it speaks OPC UA; structured results use FlatBuffers, an open format with a published schema.
- **Modular.** Each function is its own app. Add a camera or an app, or replace one, without touching the others.
- **One design for two platforms.** The same apps and the same integration run on a ctrlX CORE and on a Windows or Linux PC.

### PLC programmers and system integrators {#benefits-plc}

- **Familiar patterns.** Long operations are a ready/request handshake; short ones a single call.
- **Plain values for the PLC logic.** Status codes, counts, positions and texts are plain variables. Full results are available as structured data with their schema.
- **Any PLC with OPC UA.** On a PC, the OPC UA Connector shows every node as an OPC UA node; its NodeId is the Keryx address. On ctrlX OS, the ctrlX PLC reads the nodes directly.
- **Apps work together without the PLC in between.** By stream, the camera feeds AI Object Matching, and its results go to Calibration; the PLC only reads the final result.

### Commissioning and service {#benefits-commissioning}

- **See everything.** The [Keryx page](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html#data-layer-page) shows the whole tree: every value, its type and permissions. Write values, call functions and watch values change - without a PLC and without writing code.
- **Every module says how it is.** `control/status/code` and `control/status/text` tell what the last operation did and why it failed. See [Status Codes and Results](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html).
- **It keeps running.** Each app is a process of its own: one app that stops takes no other app with it. If the broker stops, it is started again within seconds, and the apps reconnect by themselves.
- **Results explain themselves.** Every stream result names the camera and frame it came from, the modules it passed and the settings they used - so a rejected part can be traced back to its image.

### Software developers {#benefits-developers}

- **No SDK needed to use the apps.** Any OPC UA client library, in any language, reaches every function. For scripts and tests there is the command line client `krxclient`. See [Tools](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/tools.html).
- **Test each step alone.** Call one function once, check its output, and only then chain the steps.
- **Self-describing.** Browse the tree to find nodes; the schemas of structured results are on the tree itself, under `types/hdvisionsystems/<app>/…`.
- **Bring your own function.** Algorithms and devices can be added as providers of their own, in C++ or Python, next to the LumiScan apps. Ask HD Vision Systems for the developer package.

### IT and security {#benefits-it}

- **Closed by default.** The broker accepts connections from the same PC only (`127.0.0.1`), and so does the Keryx page. Opening it to a network is a deliberate setting.
- **No cloud.** Keryx runs entirely on the machine; it needs no internet connection.
- **Control at the edge.** The OPC UA Connector can serve one part of the tree only, and can run read-only. On ctrlX OS, the apps use the ctrlX Data Layer with the user management of ctrlX OS.

> [!IMPORTANT]
> The Keryx broker and the OPC UA Connector have **no authentication and no encryption** today. Run them on one PC, or in a separate machine network you trust, behind a firewall. See [OPC UA Connector: Security](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/opc-ua.html#security).

## Good to know {#good-to-know}

- **One broker per PC.** All apps of one installation use the same broker. Several brokers on different ports are independent of each other; brokers on several PCs do not share one tree.
- **Values carry no timestamp of their own.** An app that needs one publishes it in a node or inside the result.
- **A new subscriber gets no initial value.** Read the node once, then subscribe.
- **Streams are experimental** in the current releases.

More in [LumiScan Keryx on a PC: Good to know](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html#limits).

## Where to go next {#next}

- Try it yourself in 30 minutes: [Getting Started with LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/getting-started.html).
- Install and run Keryx on a PC: [LumiScan Keryx on a PC](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html).
- Use the apps on ctrlX OS: [ctrlX Data Layer on ctrlX OS](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/ctrlx-data-layer.html).
- Find the nodes of an app: [Addresses and Modules](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/addresses.html) and the **Data Layer Reference** in the app’s manual.
- Connect a PLC: [OPC UA Connector](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/opc-ua.html) (PC) [Connecting a PLC](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/ctrlx-data-layer.html#connecting-a-plc) (ctrlX OS).

# Getting Started with LumiScan Keryx

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/getting-started.html

In this guide you try LumiScan Keryx on a Windows PC, without a camera and without a PLC. LumiScan Cam Driver with a **simulated camera** provides the nodes; you are the client - first by hand on the Keryx page, then with the command line client `krxclient`, which works exactly as a PLC would.

When you have finished, you have:

1. started the broker and looked at the tree,
2. read values and written one,
3. connected the camera with a ready/request handshake - by hand and with one command,
4. taken an image with an execute method and checked the result,
5. disconnected the camera again.

What you learn here works the same for every LumiScan app, on a PC and on ctrlX OS. The concept is explained in [What Is LumiScan Keryx?](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/what-is-keryx.html).

> [!NOTE]
> This guide uses a Windows PC. On ctrlX OS, follow [How To: Test with Example Images Instead of a Camera](https://docs.hdvisionsystems.com/en/lumiscan-cam-driver/latest/how-tos/test-with-example-images.html) in the Cam Driver manual: it connects a simulated camera and takes an image in the ctrlX OS web interface, where the Data Layer view does what the Keryx page does here.

## Before you start {#before-you-start}

- A PC with Windows 11.
- **LumiScan Keryx** and **LumiScan Cam Driver** installed: Keryx first, each installer as administrator. See [Installing on Windows](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html#installing).
- A licence for LumiScan Cam Driver: CodeMeter Runtime installed and the LumiScan Key plugged in, see [LumiScan Licensing](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/index.html).
- Optional: a few PNG images, to give the simulated camera something to deliver in step 6.

Open a **new** terminal (Command Prompt or PowerShell) after the installation, so that it knows the settings the Keryx installer made. If `krxclient` is not found, run it from the installation folder of LumiScan Keryx.

> [!TIP]
> On Ubuntu 24.04 all `krxclient` commands are the same. The Keryx page and its window are part of the Windows installation only.

## Step 1 - Start Keryx and open the Keryx page {#step-1}

1. Start **LumiScan Keryx** from the Windows Start menu.

   A window opens with the **Keryx page**. If no broker runs yet, starting LumiScan Keryx starts it.

2. Look at the tree. Without any app it is still empty: Keryx itself provides no nodes - the apps do.

The same page is available in any browser on this PC at `http://127.0.0.1:7555/`.

**Done when:** the Keryx page shows that the broker runs.

## Step 2 - Start an app with a simulated camera {#step-2}

The Cam Driver writes example settings with one simulated camera. A camera whose serial number contains `simulation` needs no hardware.

1. Write the example settings into a work folder:
   ```shell
   lumiscan-cam-driver --generate-settings C:\work\cam-driver-settings
   ```

   The Cam Driver writes `lumiscan-cam-driver.json`, the module file `lumiscan-cam-driver-example-module.json` and their schemas, names the folder it reads its settings from, and ends.

2. Open the module file and check that `id` is `camera1` and `serial` is `simulation`. If the `id` differs, use your `id` instead of `camera1` in all addresses below.

3. Copy the files into the settings folder the Cam Driver named, by default `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-cam-driver\etc\lumiscan-cam-driver`.

4. Start the Cam Driver:
   ```shell
   lumiscan-cam-driver
   ```

   Leave the terminal open: it shows the Cam Driver’s messages.

On the Keryx page the tree now has the folder `hdvisionsystems` with `lumiscan-cam-driver` in it.

**Done when:** `hdvisionsystems/lumiscan-cam-driver/system/found-modules` lists `camera1`, and the folder `hdvisionsystems/lumiscan-cam-driver/camera1` exists.

## Step 3 - Read values {#step-3}

**On the Keryx page:** open `hdvisionsystems/lumiscan-cam-driver/camera1/control/status` and select `code`. The page shows its value, its type and what may be done with it. `0` means **ready**.

**With krxclient:** open a second terminal and read the same node:

```shell
krxclient read hdvisionsystems/lumiscan-cam-driver/camera1/control/status/code
krxclient read hdvisionsystems/lumiscan-cam-driver/camera1/control/status/text
```

`krxclient` prints the value together with its type, as JSON. Three more commands help you find your way around:

```shell
krxclient browse   hdvisionsystems/lumiscan-cam-driver/camera1/control
krxclient metadata hdvisionsystems/lumiscan-cam-driver/camera1/control/capture/execute
krxclient tree     hdvisionsystems/lumiscan-cam-driver/camera1 --depth 2
```

`browse` lists the children of a folder, `metadata` shows what a node is and what may be done with it, `tree` prints a whole branch.

**Done when:** `krxclient read` shows the status code `0`.

## Step 4 - Write a value {#step-4}

Inputs are nodes that you write before you call a function. As an example, switch on the preview of the camera module, a PNG of each new image:

**On the Keryx page:** select `hdvisionsystems/lumiscan-cam-driver/camera1/input/preview/enable`, set it to `true` in its editor, and confirm.

**With krxclient:**

```shell
krxclient write hdvisionsystems/lumiscan-cam-driver/camera1/input/preview/enable true
krxclient read  hdvisionsystems/lumiscan-cam-driver/camera1/input/preview/enable
```

`krxclient write` takes the type of the node’s current value; a value that does not fit the type is refused before anything is sent.

> [!TIP]
> Add the nodes you follow to the **watch list** of the Keryx page. It shows their values as they change, which is useful in the next step.

**Done when:** `hdvisionsystems/lumiscan-cam-driver/camera1/input/preview/enable` reads `true`.

## Step 5 - Connect the camera with a handshake {#step-5}

Connecting a camera can take several seconds, so it is a **handshake**: you and the app take turns on two nodes, `ready` (set by the app) and `request` (set by you).

### By hand, on the Keryx page {#step-5-by-hand}

Put these nodes on the watch list:

- `hdvisionsystems/lumiscan-cam-driver/camera1/control/connect-camera/ready`
- `hdvisionsystems/lumiscan-cam-driver/camera1/control/connect-camera/request`
- `hdvisionsystems/lumiscan-cam-driver/camera1/control/status/code`
- `hdvisionsystems/lumiscan-cam-driver/camera1/device-info/is-connected`

Then:

1. Check that `ready` is `true`: the app can start the function.
2. Set `request` to `true`: you ask for it.
3. Watch `ready` turn `false`: the app has seen the request. The status code shows `3` (waiting for you).
4. Set `request` back to `false`: you confirm. The app now connects the camera.
5. Watch `is-connected` turn `true`, and the status code return to `0`.

> [!NOTE]
> After a successful connection, `connect-camera/ready` stays `false` - the camera is already connected. Check the result with `is-connected`, not with `ready`.

### With one command {#step-5-krxclient}

`krxclient handshake` runs the same sequence the way a PLC does. To try it, first disconnect the camera - also a handshake - and then connect it again:

```shell
krxclient handshake hdvisionsystems/lumiscan-cam-driver/camera1/control/disconnect-camera --status hdvisionsystems/lumiscan-cam-driver/camera1/control/status
krxclient handshake hdvisionsystems/lumiscan-cam-driver/camera1/control/connect-camera --status hdvisionsystems/lumiscan-cam-driver/camera1/control/status
krxclient read hdvisionsystems/lumiscan-cam-driver/camera1/device-info/is-connected
```

Each handshake prints the status code and text at the end. With `--trace handshake.jsonl` it writes every change of `ready` and of the status, with the time, into a file - a record of what the app did when.

**Done when:** `hdvisionsystems/lumiscan-cam-driver/camera1/device-info/is-connected` is `true`.

## Step 6 - Take an image with an execute method {#step-6}

Taking an image is quick, so it is an **execute method**: one write, answered when the work is done.

```shell
krxclient read    hdvisionsystems/lumiscan-cam-driver/camera1/output/package-identifier
krxclient execute hdvisionsystems/lumiscan-cam-driver/camera1/control/capture/execute
krxclient read    hdvisionsystems/lumiscan-cam-driver/camera1/control/status/code
krxclient read    hdvisionsystems/lumiscan-cam-driver/camera1/output/package-identifier
```

On the Keryx page, the same method has an **Invoke** button.

Always check two things:

1. **Could the call run?** `krxclient` exits with `0` when the app accepted the call, `1` when Keryx refused it - for example because the camera is not connected - and `2` on a timeout.
2. **Did it succeed?** The status code is `0`, and `output/package-identifier` has grown by one. The image is now on `hdvisionsystems/lumiscan-cam-driver/camera1/output/image`, with its `width`, `height` and `pixel-type`.

> [!NOTE]
> A simulated camera plays the images from its storage folder, one per capture. If the folder is empty, the capture fails: the status code is below `0`, and `control/status/text` says why. That is a useful exercise in itself. To get images, put a few PNG files into the sub-folder `camera1` of the storage folder that `system/storage` in `lumiscan-cam-driver.json` names - add a storage if there is none - restart the Cam Driver and connect again. [How To: Test with Example Images Instead of a Camera](https://docs.hdvisionsystems.com/en/lumiscan-cam-driver/latest/how-tos/test-with-example-images.html) shows the same on ctrlX OS; the settings are the same on a PC.

**Done when:** you have called `capture/execute` and read its outcome on `control/status/code`.

## Step 7 - Tidy up {#step-7}

1. Disconnect the camera:
   ```shell
   krxclient handshake hdvisionsystems/lumiscan-cam-driver/camera1/control/disconnect-camera --status hdvisionsystems/lumiscan-cam-driver/camera1/control/status
   ```
2. Stop the Cam Driver with Ctrl+C in its terminal.

The broker keeps running; the next app you start uses it again.

## What you did {#what-you-did}

| You did | On the Keryx page | With krxclient - and in a PLC or program |
| --- | --- | --- |
| Read a value | select the node | `krxclient read`; a PLC reads the OPC UA or ctrlX Data Layer node |
| Write a value | the node’s editor | `krxclient write`; a PLC writes the node |
| Run a handshake | set `request`, watch `ready` | `krxclient handshake`; a PLC sets `request` and polls `ready` every 50 to 100 ms |
| Call an execute method | **Invoke** | `krxclient execute`; over OPC UA, a method call |

## What next {#next}

- Use the apps from a PLC: [OPC UA Connector](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/opc-ua.html) on a PC [Connecting a PLC](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/ctrlx-data-layer.html#connecting-a-plc) on ctrlX OS.
- Receive every image without a call per image: [Streams](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html).
- The rules of each pattern: [Handshake](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/handshake.html) and [Execute Methods](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/execute.html).
- What the status codes mean: [Status Codes and Results](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html).
- A complete application with camera, part search and PLC: [Your First Industrial Vision Application](https://docs.hdvisionsystems.com/en/getting-started/first-application.html).

# ctrlX Data Layer and LumiScan Keryx

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/platforms.html

On ctrlX OS the LumiScan apps use the **ctrlX Data Layer** of ctrlX OS. On a PC with Windows 11 or Ubuntu 24.04 they use **LumiScan Keryx**, the Data Layer of HD Vision Systems, which offers the same interface.

## The same on both

- **Node addresses**, for example `hdvisionsystems/lumiscan-cam-driver/camera1/control/connect-camera/request`. See [Addresses and Modules](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/addresses.html).
- **Node types**: bool, integers, floating point numbers, strings, arrays, and FlatBuffers for results and images.
- **Call patterns**: [handshake](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/handshake.html), [execute methods](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/execute.html) and [streams](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html).
- **Module status codes** on `control/status/code`. See [Status Codes and Results](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html).

A program built on these works on both Data Layers. Never translate a node address between them.

## What differs

|   | ctrlX Data Layer (ctrlX OS) | LumiScan Keryx (PC) |
| --- | --- | --- |
| Provided by | ctrlX OS | The broker of **LumiScan Keryx**. An app starts it when none is running. See [LumiScan Keryx on a PC](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html) |
| Default address | managed by ctrlX OS | `tcp://127.0.0.1:5555`, on this PC only |
| Looking at the nodes by hand | the ctrlX OS web interface | the Keryx page `http://127.0.0.1:7555/`, **LumiScan Keryx Utilities** (Windows) and `krxclient`. See [Tools](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/tools.html) |
| Connecting a PLC | ctrlX PLC on the same device | the [OPC UA Connector](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/opc-ua.html) |
| Result of a method call | `DL_OK`, `DL_INVALID_VALUE`, … | `Ok`, `Rejected`, … See [Results of a method call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#method-results) |
| Settings files of an app | uploaded through the ctrlX web interface or WebDAV, see the app’s manual | ordinary files on the PC, see [Where the files are](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html#files) |
| Licence | See [LumiScan Licensing](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/index.html): on ctrlX OS a ctrlX licence, on a PC the LumiScan Key |   |

## Product manuals

The product manuals say which Data Layer they mean with the words **ctrlX Data Layer** and **LumiScan Keryx**. Where they write only "Data Layer", the statement holds for both.

# LumiScan Keryx on a PC

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html

> [!NOTE]
> On ctrlX OS the apps use the ctrlX Data Layer instead: see [ctrlX Data Layer on ctrlX OS](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/ctrlx-data-layer.html).

**LumiScan Keryx** is the Data Layer of HD Vision Systems for PCs. It offers the same interface as the ctrlX Data Layer; the name comes from the Greek *kēryx*, the herald.

On a PC the LumiScan apps exchange their data through LumiScan Keryx. One program, the **broker**, connects them: every app registers its nodes there, and every client - another app, Cockpit, the OPC UA Connector, your program - reads, writes and calls through it.

## The broker {#broker}

|   |   |
| --- | --- |
| Program | `krxsystem`, part of **LumiScan Keryx** |
| Default address | `tcp://127.0.0.1:5555`. The broker also uses the next port, 5556, for its notifications |
| Reachable from | this PC only (`127.0.0.1`): the broker has no authentication |
| One per PC | All apps of one installation use the same broker |

**You normally do not start the broker yourself.** When an app starts and no broker answers on this PC, it starts `krxsystem` as a separate process. Several apps started together start one broker. The broker keeps running when the apps end, and the apps start it again if it stops. Providers register again and subscriptions are renewed by themselves once the broker answers.

The first start is slower: the broker takes a few seconds to answer. An app that starts in that time logs that it is waiting for the broker, and connects as soon as it answers.

The **OPC UA Connector** is the exception: it never starts a broker. Start it after the apps, see [OPC UA Connector](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/opc-ua.html).

## Installing on Windows {#installing}

1. Install **LumiScan Keryx** first, then the apps.
2. Run each installer as administrator. To reinstall the same version, uninstall the old one first: an installer only accepts a higher version.
3. Open a **new** terminal before you start an app from the command line.

The LumiScan Keryx installer sets two machine-wide environment variables, `HDV_KERYX_BROKER` and `HDV_KERYX_PAGE`. They tell every app which broker program to start and which program shows the Keryx page. A program or terminal that was already open does not see them. Without them, an app starts the `krxsystem` beside its own program.

## The Keryx page {#data-layer-page}

Every broker comes with a web page that shows its tree: `http://127.0.0.1:7555/` for the default broker (the broker’s port + 2000). Starting **LumiScan Keryx** opens the same page in a window, and starts the broker if none runs.

- Select a node to see its value, type and permissions.
- A writable node has an editor, and a method has an **Invoke** button.
- A watch list follows values as they change.
- **Shut down broker** stops the broker. The apps keep running and wait: they do not start it again until you click **Start broker**, open the LumiScan Keryx window, start a `krxsystem` by hand, or restart the PC.

The LumiScan Keryx window and the Keryx page are part of the Windows installation.

## Starting the apps {#start-order}

Start the apps in any order. Wait until each has finished starting before you rely on its nodes. Start the OPC UA Connector last.

Check the start on the Keryx page (Windows) or with `krxclient tree hdvisionsystems --depth 1`: the tree shows the folder `hdvisionsystems` with one folder per running app. For each app that has modules, `hdvisionsystems/<app>/system/found-modules` lists them. If a list is empty, `hdvisionsystems/<app>/system/status-text` says why - most often a settings file that could not be loaded, or a missing licence.

To stop an app, press Ctrl+C in its console. The broker keeps running.

## Where the files are {#files}

| What | Where |
| --- | --- |
| Programs | the installation folder chosen in the installer (`Program Files`) |
| Settings of an app | `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\<program>\etc\<settings folder>`, or `%APP_RESOURCE_DIR%\etc\<settings folder>` when the environment variable `APP_RESOURCE_DIR` is set. The settings folder of each app is named in its manual |
| Broker log, records and settings (`broker.json`) | `C:\ProgramData\HD Vision Systems GmbH\LumiScan Keryx` |

On Ubuntu the broker keeps its log, records and settings in `/tmp/lumiscan-keryx`.

Every app that has settings writes an example of them into a folder of your choice, and ends:

```shell
lumiscan-cam-driver --generate-settings C:\work\cam-settings
```

It never overwrites a file. Edit the example, copy it into the settings folder and start the app.

## Options and environment variables {#options}

The same options work for every app.

| Option or variable | Effect |
| --- | --- |
| `--keryx-url <address>` | The broker to use. Default `tcp://127.0.0.1:5555`. Pass the same address to every app, to Cockpit and to the OPC UA Connector |
| `LUMISCAN_KERYX_URL` | The same, for every program on the PC. The option wins |
| `--no-keryx-autostart`, `LUMISCAN_KERYX_AUTOSTART=0` | The app does not start a broker. Start one yourself: `krxsystem --backend hdv --url <address>` |
| `HDV_KERYX_BROKER`, `HDV_KERYX_PAGE` | Set by the LumiScan Keryx installer: the broker program and the page program |

Each app names the broker address it uses in its log at start.

## Addresses other than the default {#several-brokers}

- **Another port**: `tcp://127.0.0.1:<port>`. Each port is its own broker, started by the first app that needs it. A broker takes its port and the next one, so two brokers need ports at least two apart. Its Keryx page is on the port + 2000.
- **A local socket**: `ipc://<name>`. A relative name is relative to the folder a program starts in: start the broker yourself and start every app from that same folder.
- **Another PC**: an address of another computer is only connected to, never started. The broker listens on this PC only unless its settings say otherwise, and it has no authentication. Running apps on several PCs against one broker is not covered by this manual.

## Good to know {#limits}

- Values carry no timestamp of their own: an app that needs one publishes it in a node or inside the result.
- A new subscriber gets no initial value. Read the node once, then subscribe.
- A method call that is repeated after a timeout can run twice.

# ctrlX Data Layer on ctrlX OS – LumiScan Keryx

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/ctrlx-data-layer.html

> [!NOTE]
> On a PC with Windows 11 or Ubuntu 24.04 the apps use LumiScan Keryx instead: see [LumiScan Keryx on a PC](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html).

On ctrlX OS - a ctrlX CORE or a ctrlX IPC - the LumiScan apps are installed from the ctrlX Store and use the **ctrlX Data Layer** of ctrlX OS. There is nothing to install or start for the Data Layer itself.

## Where the nodes are

Every app registers its nodes under `hdvisionsystems/<app>/…`, with the same addresses as on a PC. See [Addresses and Modules](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/addresses.html). Look at them, write them and call methods in the Data Layer view of the ctrlX OS web interface.

## Connecting a PLC {#connecting-a-plc}

A ctrlX PLC program on the same device reads, writes and calls the nodes of the apps directly.

- Use the plain nodes - numbers, booleans, strings and arrays - for PLC logic.
- Results that are FlatBuffers messages need their schema to be decoded. AI Object Matching provides its schema and describes how to import it into ctrlX PLC Engineering in its manual.

## Results of a method call

A method call answers with a ctrlX result: `DL_OK` when it ran, otherwise for example `DL_TOO_MANY_OPERATIONS` or `DL_INVALID_VALUE`. The meaning of each is in [Results of a method call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#method-results).

## Settings files

The settings of each app are files in the app’s folder of the active configuration, `/var/snap/rexroth-solutions/common/solutions/activeConfiguration`. Upload them through the ctrlX web interface, or with WebDAV where direct upload is not available. Each app’s manual describes its files under **Uploading Data**. Settings can also be changed on the Data Layer, see [Settings, Modules and Restart](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/settings-and-modules.html).

## Logs

An app writes its messages to the ctrlX OS system log. Read them in the Logbook of the ctrlX web interface, or with `journalctl`.

An app without a valid licence stops shortly after it starts; the reason is in the system log. See [LumiScan Licensing](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/index.html).

# Addresses and Modules – LumiScan Keryx

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/addresses.html

## The address of a node

```none
hdvisionsystems/<app>/<module>/<folder>/...     the nodes of one module
hdvisionsystems/<app>/system/...                what concerns the whole app, or more than one module
types/hdvisionsystems/<app>/<type>              the FlatBuffers types the app publishes
```

- **`<app>`:** The app’s name on the Data Layer, lower case with `-`, for example `lumiscan-cam-driver`. It is not always the name of the program: the program `lumiscan-ai-obj-mat` serves `lumiscan-ai-object-matching`, and `lumiscan-calib` serves `lumiscan-calibration`.
- **`<module>`:** One instance inside the app: a camera, a neural network, a calibration plane, a finder module. Its name comes from the app’s settings. The code readers have no module level.

Example: `hdvisionsystems/lumiscan-cam-driver/camera1/control/connect-camera/request`.

## Module names {#module-names}

- Addresses are **lower case**. A node you cannot find is nearly always a difference in case or spelling.
- Module names consist of lower-case letters, digits, `-` and `_`. The Cam Driver and AI Object Matching refuse any other module name: such a module does not appear on the Data Layer. Calibration names a module after its file and uses the name in lower case.
- `system` is reserved and is never a module name.

## The folders of a module {#folders}

| Folder | Holds |
| --- | --- |
| `control/` | the functions: `control/<function>/ready` and `request` (a [handshake](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/handshake.html)), `control/<function>/execute` (an [execute method](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/execute.html)); the module’s status `control/status/code` and `control/status/text`; the [streams](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html) `control/publish/`, `control/subscribe/` and `control/unsubscribe/` |
| `input/` | what a client writes before it starts a function |
| `output/` | the results of the functions, read-only |
| `setting/` | a read-only view of what the module applies, for example `setting/settings-hash` and `setting/stream/…` |

Some apps have folders of their own, for example the Cam Driver’s `device-info/`, `transport-layer/` and `features/`.

## Where a function keeps its nodes {#layout}

**An execute method** keeps everything it owns under its function:

```none
<module>/control/<function>/execute
<module>/control/<function>/input/...
<module>/control/<function>/output/...
```

**A handshake** has `ready` and `request` under its function, and uses the inputs and outputs of the module:

```none
<module>/control/<function>/ready
<module>/control/<function>/request
<module>/input/...
<module>/output/...
<module>/control/status/code, text
```

**A function that has both** - most functions of the Cam Driver, AI Object Matching and Calibration - uses the module’s `input/` and `output/` for both ways of calling it.

## The layout of each app {#layouts-per-app}

Some apps keep an older layout so that programs written against them keep working.

| App | Module named by | Functions |
| --- | --- | --- |
| Cam Driver | `id` in the module file | `<module>/control/<function>/…` |
| AI Object Matching | `name` in the module file, `default` if none | `<module>/control/<function>/…` |
| Calibration | the module file’s name without `.json` | `<module>/control/<function>/…` |
| Template Finder, Object Finder, Area Detector, Text Reader | the module id given to `system/create-module`, or the saved module list; `module-1` by default | `<module>/<method>/execute`, `<module>/<method>/input/…`, `<module>/<method>/output/…`, for example `module-1/find-template/execute`; streams under `<module>/control/` |
| DMC, QR, Aztec and Barcode Reader | no module level | `<app>/execute`, `<app>/input/…`, `<app>/output/results`; streams under `<app>/control/` |
| Cockpit | none: Cockpit only reads the nodes of the other apps |   |

The exact nodes of each app are in its manual’s **Data Layer Reference**.

## The system node {#system}

Everything that is not about one module is under `hdvisionsystems/<app>/system/`: making and removing modules, the settings files, device discovery, and resources shared by all modules. The code readers have only `system/meta/subscription-schema` there. See [Settings, Modules and Restart](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/settings-and-modules.html).

## Types {#types}

| Type | Used for |
| --- | --- |
| bool, int16, int32, uint32, uint64, float32, float64, string | plain values: inputs, flags, counters, status codes (`int32`) |
| arrays of these | for example the coordinate arrays of Calibration |
| FlatBuffers | results and images. Their schemas are on the Data Layer under `types/hdvisionsystems/<app>/…` |

Build PLC logic on the plain values. A FlatBuffers result needs its schema to be decoded; every result a PLC usually needs is also available as plain nodes - see the app’s manual.

# Choosing a Pattern – LumiScan Keryx

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/calling-functions.html

Every function of a LumiScan app is called in one of three ways.

|   | [Handshake](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/handshake.html) | [Execute method](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/execute.html) | [Stream](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html) |
| --- | --- | --- | --- |
| For | operations longer than about 1 s, or of unknown length | operations within about 1 s | every item a source produces, as it arrives |
| The client | writes `request`, polls `ready` and the status; nothing blocks | writes the method once; the write returns when the operation is done | subscribes once; the apps push every result |
| The outcome | `control/status/code` and the outputs | the result of the write (could it run?), then the status (did it succeed?) | each pushed result |
| Examples | `connect-camera`, `reset`, `inference` | `capture`, `trigger`, `transform`, `find-template` | camera frames into AI Object Matching, a finder or a code reader |

## Why about 1 s

An execute method holds its caller until the operation has finished: a PLC task, or a client whose request times out. On LumiScan Keryx, a client gives up after 2 s by default. An operation that can take longer is therefore a handshake, which the caller polls instead of waiting. This is why the Cam Driver offers `connect-camera`, `disconnect-camera` and `reset` as handshakes only.

## On request or as a stream

|   | On request (handshake or execute) | Stream |
| --- | --- | --- |
| Who starts the work | your program: one call per image or per point | the source: every image the camera delivers starts the next app |
| How the apps relate | independent; your program carries the data from one to the next | chained; each app subscribes to the one before it |
| Speed (one camera, one PC, as measured) | about 34 images per second from the Cam Driver | 63 to 68 images per second from the Cam Driver |

Use **on request** for single, slow or irregular operations: connect the camera, take one image, transform a few points you already have. Use a **stream** for continuous work: the camera delivers an image, AI Object Matching finds the objects, Calibration turns them into coordinates, and your program only reads the result.

**One implementation, several patterns.** Where an app offers the same work in more than one pattern, they share one implementation and one lock per module. The result is the same, and two operations of one module never overlap.

## Which app offers what

| App | Handshake | Execute | Stream |
| --- | --- | --- | --- |
| Cam Driver | yes | yes | produces frames |
| AI Object Matching | yes | yes | consumes frames, produces detections |
| Calibration | yes | yes | consumes points or results, produces 3D points |
| Template Finder, Object Finder, Area Detector, Text Reader | – | yes | consume frames, produce results |
| DMC, QR, Aztec and Barcode Reader | – | yes | consume frames, produce codes |

Each app’s manual lists its functions and which patterns each one offers.

# Handshake – LumiScan Keryx

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/handshake.html

The handshake is for an operation that can take longer than about 1 s, or that a client must start without waiting for it. Client and module take turns on two nodes, `ready` and `request`. Nobody waits inside a call: the client polls, and the module answers through nodes.

The Cam Driver, AI Object Matching and Calibration offer handshakes.

## Addresses {#addresses}

| Address | Type | Meaning |
| --- | --- | --- |
| `<module>/control/<function>/ready` | bool, read-only | set by the module: `true` when the function can be started |
| `<module>/control/<function>/request` | bool, writable | set by the client to start the function |
| `<module>/control/status/code` | int32, read-only | the module’s status, one for all its functions. See [Status Codes and Results](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html) |
| `<module>/control/status/text` | string, read-only | the same as text, for people - use the code in program logic |
| `<module>/input/…` | writable | the function’s inputs, written before the request |
| `<module>/output/…` | read-only | its results |
| `<module>/output/package-identifier` | read-only | counts finished operations: a new value means new outputs |

`<module>` is `hdvisionsystems/<app>/<module name>`, for example `hdvisionsystems/lumiscan-calibration/plane1/control/transform/request`.

## The sequence {#sequence}

1. Wait until `control/<function>/ready` is `true`.
2. Write the function’s inputs.
3. Set `control/<function>/request` to `true`.
4. Wait until `ready` is `false`: the module has seen the request.
5. Set `request` to `false`.
6. Wait until `ready` is `true` again: the function has finished.
7. Read `control/status/code` and the results under `output/`. `output/package-identifier` has grown by one.

Poll at 50 to 100 ms.

## What the module shows {#module-states}

As Calibration runs it:

| Step | `ready` | `request` | `status/code` |
| --- | --- | --- | --- |
| Idle | `true` | `false` | `0` ready, or the last error |
| The client requests | `true` | `true` |   |
| The module acknowledges | `false` | `true` | `3` waitingForClient |
| The client confirms; the function runs | `false` | `false` | `2` running |
| Done | `true` | `false` | `0`, or an error (below `0`) |

## Rules {#rules}

- **Only one program writes a `request` node.** Two programs writing it independently can lose a request. A program that cannot coordinate with others uses the [execute method](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/execute.html), which refuses a second call while one runs.
- **The module waits for `request` to fall, for as long as it takes.** There is no timeout: a `request` still `true` afterwards would be read as a new request.
- **A handshake and an execute method of the same module share one lock.** While a handshake runs, an execute call of the same module answers that it is busy.

## How the apps differ {#differences}

Calibration follows the sequence exactly. The Cam Driver and AI Object Matching differ in ways a PLC program must know:

| App | Difference |
| --- | --- |
| Cam Driver | `capture` starts as soon as the request is seen, without waiting for `request` to fall. A **failed capture ends at status `3`**, not at its own error code, and `capture/ready` stays `false` until a `reset` succeeds. A failed `reset`, `save` or `load` also stays until a `reset` succeeds. Any other error stays on the status for about 100 ms only: check a connection with `device-info/is-connected`, not with the status. Without a licence every `ready` is `false` and the status is `-4`. |
| AI Object Matching | `inference` starts as soon as the request is seen and **ends at status `3` whatever its outcome**; only `output/package-identifier`, which grows on success alone, tells that it succeeded. After a failed inference, and while the module has an error, every request but `reset` is ignored. `reset` runs at once. While the stream runs, `inference/ready` is `false` and a request gets status `100002`. |

To read the outcome of a Cam Driver `capture` or an AI `inference` directly, use its execute method: the status then keeps the operation’s own code.

# Execute Methods – LumiScan Keryx

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/execute.html

An execute method is for an operation that finishes within about 1 s. The client writes any value to the method’s `execute` node, and the write returns when the operation has finished. One write, no state to track.

## Calling a method

1. Write the method’s inputs. A method has no arguments of its own: its inputs are separate nodes.

2. Write to the method’s `execute` node, for example `hdvisionsystems/lumiscan-cam-driver/camera1/control/capture/execute`.

3. Check **both** results:

   a. **The result of the write: could the operation run at all?** A refused write is never queued. See [Results of a method call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#method-results).

   b. **The outcome: did the operation succeed?** Where to read it depends on the app, see below.

4. Read the outputs.

## Where the inputs, outputs and outcome are {#where}

| Apps | Nodes | A failed operation shows as |
| --- | --- | --- |
| Cam Driver, AI Object Matching, Calibration | `<module>/control/<function>/execute`; the module’s `input/…` and `output/…`, the same the handshake uses | `control/status/code` and `text`, while the write itself answers that it ran. **Always read the status after the write.** A refused write leaves the status as it was |
| Template Finder, Object Finder, Area Detector, Text Reader | `<module>/<method>/execute`, `<module>/<method>/input/…`, `<module>/<method>/output/result`, `output/status-code`, `output/status-text` | `<method>/output/status-code` and `status-text`, **and** the write fails with the matching result |
| DMC, QR, Aztec and Barcode Reader | `<app>/execute`, `<app>/input/…`, `<app>/output/results` | the write fails; the reason is in the application log |

The finders' `status-code` has its own values, see [Execution status of the finders](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#execution-status).

The functions under `system/` of every app are methods of the second kind: `system/<function>/execute` with `input/…` and `output/status-code`, `status-text`. A function of the whole app in the newer layout is `system/control/<function>/execute`, for example `system/control/restart/execute`.

## When a method runs {#ready}

A method of the Cam Driver, AI Object Matching or Calibration checks the same `control/<function>/ready` signal its handshake uses, and is refused while it is `false`. Most functions depend on something that must happen first - a connected camera, a loaded network, an image to save. The app’s manual says when each `ready` is `true`.

When a method is refused, read its `ready` together with `control/status/code` and `status/text`: `ready` names the missing precondition, and the status text still carries the message of the fault that caused it.

## Timeouts {#timeouts}

Keep in mind that the caller is blocked until the method returns. On LumiScan Keryx a client gives up after 2 s by default; the OPC UA Connector waits up to 60 s for a method call. A function that can take longer is offered as a [handshake](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/handshake.html) only.

## One operation at a time {#busy}

A module runs one operation at a time. A method called while another operation of the same module runs - an execute, a handshake, or in the finders a frame of a stream - is refused as busy (`TooManyOperations`, ctrlX `DL_TOO_MANY_OPERATIONS`). Retry it: the same call succeeds once the running operation has finished.

An operation that collides with a running stream is refused differently: the Cam Driver’s `capture` and AI Object Matching’s `inference` are not ready while their stream runs (`InvalidOperationMode`, ctrlX `DL_INVALID_OPERATION_MODE`). Retrying does not help; stop the stream first, see [Streams](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html#collisions).

# Streams (Experimental) – LumiScan Keryx

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html

> [!IMPORTANT]
> Streams are **experimental**: in the Cam Driver from v2.3.0, in AI Object Matching from v2.2.0 and in Calibration from v2.1.0. Their nodes may still change. Verify a stream with your camera and network before you rely on it.

A stream processes every item a source produces, as it arrives: camera frames into AI Object Matching, a finder or a code reader; detections or points into Calibration. There is no request per item. The producer pushes each item, a consumer processes it and pushes its result. Producer and consumer work at the same time, which is why a stream is faster than one execute call per item.

## Producers and consumers {#roles}

| App | Role |
| --- | --- |
| Cam Driver | produces frames on `<camera>/control/publish/output/stream/frame` |
| AI Object Matching | consumes frames, produces detections on `<module>/control/subscribe/output/stream/result` |
| Template Finder, Object Finder, Area Detector, Text Reader | consume frames, produce their results on `<module>/control/subscribe/output/stream/result` |
| DMC, QR, Aztec and Barcode Reader | consume frames, produce codes on `<app>/control/subscribe/output/stream/result` |
| Calibration | consumes points or another app’s result, produces 3D points on `<module>/control/subscribe/output/stream/points` and `plain-points` |

**A consumer has one source.** To process two cameras, use two modules.

## The producer: the Cam Driver {#producer}

All addresses start with `hdvisionsystems/lumiscan-cam-driver/<camera>/`.

| Address | Type | Meaning |
| --- | --- | --- |
| `control/publish/execute` | method | applies the inputs below together |
| `control/publish/input/enable` | bool | publish while `true` |
| `control/publish/input/keep-latest-output` | bool | also write each frame to the normal output |
| `control/publish/input/tag` | string | the tag on its frames; saved in the module file |
| `control/publish/output/stream/frame` | FlatBuffers | each frame, pushed |
| `control/publish/output/stream/active` | bool | the stream runs |
| `control/publish/output/stream/statistics/…` | uint64 | counters |

The Cam Driver never triggers the camera by itself. A frame comes when the camera is triggered by hardware or by `control/trigger/execute`, or when its trigger mode is off and it runs freely. The stream needs a connected camera; `connect-camera`, `disconnect-camera` and `reset` stop a running stream. See the Cam Driver manual.

## A consumer {#consumer}

The same nodes in every consumer, under `<module>/` (a code reader: under `<app>/`):

| Address | Type | Meaning |
| --- | --- | --- |
| `control/subscribe/execute` | method | checks, saves and applies the inputs below |
| `control/subscribe/input/enable` | bool | stream mode |
| `control/subscribe/input/address` | string | the one source: the producer’s stream **folder** |
| `control/subscribe/input/tag` | string | the tag on this module’s output; empty: the module id |
| `control/subscribe/input/queue-size` | uint32 | how many items may wait |
| `control/subscribe/input/keep-latest-output` | bool | also write each result to the normal output |
| `control/unsubscribe/execute` | method | drops the source named by … |
| `control/unsubscribe/input/address` | string | … this address; another address is refused |
| `setting/stream/…` | read-only | what is applied and saved: `enable`, `address`, `tag`, `queue-size`, `keep-latest-output` |
| `control/subscribe/output/stream/active` | bool | the stream runs |
| `control/subscribe/output/stream/<result>` | FlatBuffers | each result, pushed |
| `control/subscribe/output/stream/statistics/…` | uint64 | counters, published every 250 ms, reset at each start |

The finders and code readers also have `control/subscribe/output/stream/last-failure`: why the last item failed.

What a consumer’s source must hold is on `hdvisionsystems/<app>/system/meta/subscription-schema`, as a JSON Schema.

## Starting and stopping a stream {#running}

**The inputs take effect only on `execute`.** Writing `enable` alone starts nothing.

1. Start the producer: on the camera write `control/publish/input/enable` = `true`, then call `control/publish/execute`. Wait until `control/publish/output/stream/active` is `true`.
2. On the consumer write `control/subscribe/input/address`, for example `hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream`.
3. Optionally write `tag`, `queue-size` and `keep-latest-output`.
4. Write `control/subscribe/input/enable` = `true`, then call `control/subscribe/execute`.
5. Wait until `control/subscribe/output/stream/active` is `true`. Results arrive from then on.
6. To stop, write `enable` = `false` and call `execute` again.

Good to know:

- Stream mode is a **level**, not a command: the stream runs for as long as the applied `enable` is `true`.
- The inputs start with what is applied, so change only what you need and call `execute`.
- A consumer can be started before its producer. Results arrive once items do. A subscription that fails is tried again every 5 s while the stream runs.
- Another address replaces the source.
- `enable` = `true` without an address is refused (`Rejected`, ctrlX `DL_INVALID_VALUE`), and nothing changes.

## Calibration as a consumer {#calibration-source}

Calibration is given a stream folder too, and its module file says which node in it to read and how to turn it into points: an `onEntry` step in the `stream` section. To read the objects AI Object Matching finds, the step names the node `result`, the list in it and the fields that are the point. Without such a step Calibration reads its source as a plain array of numbers, as a PLC variable delivers them. See the Calibration manual.

## Keep latest output {#keep-latest}

With `keep-latest-output` on, every item - or every result - is also written to the module’s normal output, as an on-request call would write it, and `output/package-identifier` is counted. A PLC that reads the normal output then sees the latest streamed result. With it off, the stream publishes only under `…/stream/…`, and the normal output keeps the result of the last call.

Stream results are FlatBuffers records. For a PLC, switch on `keep-latest-output` in the module whose result you need and read its plain output nodes. Calibration also publishes `plain-points`: all points of one result in one `float32` array `x0, y0, z0, x1, …`, without lineage.

## What is kept across a restart {#saved}

| What | Kept | How |
| --- | --- | --- |
| A consumer’s stream (`enable`, `address`, `tag`, `queue-size`, `keep-latest-output`) | yes | `control/subscribe/execute` and `control/unsubscribe/execute` save them in the `stream` section of the module’s settings file before they apply them. A consumer whose saved `enable` is `true` subscribes by itself at start |
| The Cam Driver’s stream | **no** | only its `tag` is saved. After every start call `control/publish/execute` with `enable` = `true` again |
| The camera connection | no | run the `connect-camera` handshake after every start |

A file that cannot be written makes `execute` answer `CreationFailed` (ctrlX `DL_CREATION_FAILED`), and nothing changes.

The `stream` section of a consumer’s settings file:

```json
"stream": {
    "enable": false,
    "address": "hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream",
    "tag": "",
    "queueSize": 1,
    "keepLatestOutput": false,
    "onEntry": []
}
```

## Queue size {#queue}

| App | Range | Default | When the queue is full |
| --- | --- | --- | --- |
| AI Object Matching, the finders, the code readers | 1 to 64 | 1 | a new item pushes out the oldest |
| Calibration | 1 to 4096 | 64 | a new item pushes out the oldest waiting one |

An item pushed out of a full queue counts as **skipped**.

## Streams and single operations {#collisions}

While a stream runs, operations it would collide with are refused:

- Cam Driver: `capture/ready` is `false`; `capture/execute` answers `InvalidOperationMode` (ctrlX `DL_INVALID_OPERATION_MODE`). Do not retry in a loop. To take single images while streaming, read the camera’s `…/stream/frame`, or switch on `keep-latest-output` and read `output/image` when `output/package-identifier` changes.
- AI Object Matching: `inference/ready` is `false`; a handshake request ends with status `100002`.
- Finders: a method called while a frame is processed is refused as busy.
- Code readers: `execute` and the stream do not hold each other up; each frame is read by a detector of its own.

Stopping the Cam Driver’s stream makes it reconnect the camera so that `capture` works again; this takes about two seconds. Wait until `capture/ready` is `true`. Switch between stream and capture as rarely as you can.

## Following the chain {#counters}

Each app counts what it receives under `…/stream/statistics/`. The first counter that does not grow shows where a chain stops:

| App | Counters |
| --- | --- |
| Cam Driver | `frames`, `published-frames`, `lost-frames`, `incomplete-frames` |
| AI Object Matching | `received-frames`, `inferred-frames`, `skipped-frames`, `failed-frames`, `lost-frames` |
| Finders, code readers | `received-frames`, `processed-frames`, `skipped-frames`, `failed-frames`, `lost-frames` |
| Calibration | `received-updates`, `transformed-updates`, `skipped-updates`, `failed-updates`, `lost-updates` |

`lost-` counts items that never arrived, found from gaps in the sequence numbers; `skipped-` items pushed out of a full queue; `failed-*` items that could not be processed.

## The result: an envelope with its lineage {#envelope}

Every stream result is an **envelope**: the item’s lineage, then the payload - the same result as the app’s non-stream output, with a few differences described in each app’s manual.

The **lineage** lists every module the item passed. Each step has:

| Field | Meaning |
| --- | --- |
| `producer` | the Data Layer address of the module, for example `hdvisionsystems/lumiscan-cam-driver/camera1` |
| `tag` | the module’s tag, or its module id when the tag is empty |
| `run` | when the producer’s stream started (µs since the epoch); a new run numbers from 1 again |
| `sequence` | the item’s number in the run: 1, 2, … without gaps, so a gap is a lost item |
| `time_us` | when the step was made |
| `settings_hash` | the hash of the settings the step was made with, as on `setting/settings-hash` |
| `elapsed_us` | how long the step took |
| `external_id` | the producer’s own number for the item, for example the camera’s block id |

The lineage keeps at most 16 steps: the origin and the newest. A changed `settings_hash` means a setting changed. Each hash is saved once in `settings-history/` in the app’s settings folder, so the settings behind a result can be looked up.

To follow one image through the chain on a PC, use **LumiScan Keryx Utilities**, see [Tools](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/tools.html#utilities).

# Status Codes and Results – LumiScan Keryx

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html

Two kinds of answers tell a client what happened:

- the **result of a call** - did the write or method call go through? - see [Results of a method call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#method-results);
- the **status** the app writes into a node - did the operation succeed? - see [Module status: `control/status/code`](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#module-status) and [Execution status of the finders](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#execution-status).

Use the numbers in program logic, never the texts.

## Module status: `control/status/code` {#module-status}

The Cam Driver, AI Object Matching and Calibration report the state of each module on `<module>/control/status/code` (`int32`) and `control/status/text`. The values `0` and above are normal, values below `0` are errors.

| Code | Text | Meaning |
| --- | --- | --- |
| `0` | `ready` | the last function succeeded; ready for the next |
| `1` | `settingUp` | the module is starting |
| `2` | `running` | a function runs |
| `3` | `waitingForClient` | waiting for the client, usually for `request` to fall |
| `-1` | `undefinedError` | no specific code |
| `-2` | `invalidSetting` | the settings could not be loaded |
| `-3` | `invalidInput` | an input is not valid |
| `-4` | `missingLicense` | the licence is missing |
| `-5` | `restartRequired` | the settings were changed through `system/settings`: restart the app |

App-specific codes, listed in each app’s manual:

| App | Codes |
| --- | --- |
| Cam Driver | `-10000` to `-10012` |
| Calibration | `-10001` (`inputXYSizeNotEqual`) |
| AI Object Matching | `100001` (`ImageQueueEmpty`), `100002` (`StreamActive`) |

## Execution status of the finders {#execution-status}

Template Finder, Object Finder, Area Detector and Text Reader write the outcome of each method to `<method>/output/status-code` (`int16`) and `status-text`. These values are their own, not the module status above:

| Code | Text |
| --- | --- |
| `1` | `ok` |
| `0` | `idle` |
| `-1` | `busy` |
| `-2` | `invalidInput` |
| `-3` | `imageReadFailed` |
| `-4` | `sourceNotFound` |
| `-5` | `cropInvalid` |
| `-6` | `writeFailed` |
| `-7` | `algorithmFailed` |
| `-8` | `publishFailed` |
| `-9` | `moduleNotFound` |
| `-10` | `moduleExists` |
| `-11` | `licenseUnavailable` |

Note that `-5` means `cropInvalid` here, but `restartRequired` in the module status.

## Results of a method call {#method-results}

A write to an `execute` node answers whether the operation could run. The names differ between the Data Layers; the meaning is the same.

| LumiScan Keryx | ctrlX Data Layer | OPC UA Connector | Meaning and what to do |
| --- | --- | --- | --- |
| `Ok` | `DL_OK` | `Good` | It ran. For the Cam Driver, AI Object Matching and Calibration, read `control/status/code` for the outcome |
| `TooManyOperations` | `DL_TOO_MANY_OPERATIONS` | `BadTooManyOperations` | Another operation of the module runs. Retry |
| `InvalidOperationMode` | `DL_INVALID_OPERATION_MODE` | `BadInvalidState` | The function is not ready: its `ready` is `false`, no licence, the camera is not connected, a stream runs. Bring the module into the state first; retrying alone keeps failing |
| `ResourceUnavailable` | `DL_RESOURCE_UNAVAILABLE` | `BadResourceUnavailable` | The app is stopping, a restart is required (status `-5`), or an AI module is in error. Read the status; restart the app when required |
| `Rejected` | `DL_INVALID_VALUE` | `BadRequestNotAllowed` | An input is not valid. Nothing changed. Correct the input |
| `NodeNotFound` | `DL_INVALID_ADDRESS` | `BadNodeIdUnknown` | An image, a source, a module or the node itself was not found. Check the address and its case |
| `CreationFailed` | `DL_CREATION_FAILED` | `BadCommunicationError` or `BadInternalError` | Something could not be written or made: a file, an existing module, an unavailable licence. The log says why |
| `InternalError` | `DL_FAILED` | `BadInternalError` | The operation failed. Read the status or the log |

On the ctrlX Data Layer, data a method attaches to a failed call does not reach the client, so a refused call carries no reason. The apps therefore write the reason to their log and, where they have one, to a status node.

# Settings, Modules and Restart – LumiScan Keryx

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/settings-and-modules.html

Everything that is not about one module is under `hdvisionsystems/<app>/system/`. The apps come in two families that handle their modules differently. The code readers have only `system/meta/subscription-schema` there (see [Streams](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html#consumer)).

## Cam Driver, AI Object Matching, Calibration: settings files {#settings-file-apps}

Their modules are the module files that the application settings file lists.

| Node | Kind | What it does |
| --- | --- | --- |
| `system/settings` | string, read and write | All loaded settings as one JSON document: the application file, with each listed module file inlined (passwords shown as `*`). Writing it saves the changed files - each checked by the app first, the old one kept as `.bak` - and marks a restart as required |
| `system/restart-required` | bool, read-only | `true` after a saved change, until the app restarts. Meanwhile every module reports status `-5` (`restartRequired`), and its methods answer `ResourceUnavailable` (ctrlX `DL_RESOURCE_UNAVAILABLE`) |
| `system/control/restart/execute` | method | stops the app and starts it again. The app’s nodes disappear until it is up: wait until `system/restart-required` can be read again |
| `system/control/create-module/execute` | method, inputs `control/create-module/input/module-id` and `content` | writes `<module-id>.json`. Refused when the file exists |
| `system/control/activate-module/execute`, `system/control/deactivate-module/execute` | method, input `control/<function>/input/module-id` | adds the file to, or removes it from, the application file’s list. The file stays. Needs a restart |
| `system/found-modules`, `system/status-text` | read-only | the modules served; why none are |

The Cam Driver adds camera discovery: `system/found-camera-modules`, `found-camera-serials`, `found-camera-mac-addresses`, `found-camera-ip-addresses`, and the `system/force-ip/` handshake. AI Object Matching serves one module at most: `activate-module` refuses a second.

Example - add the camera module `camera2` to the Cam Driver:

1. Write the module’s JSON to `hdvisionsystems/lumiscan-cam-driver/system/control/create-module/input/content` and `camera2` to `control/create-module/input/module-id`, then call `control/create-module/execute`.
2. Write `camera2` to `control/activate-module/input/module-id`, then call `control/activate-module/execute`.
3. Call `hdvisionsystems/lumiscan-cam-driver/system/control/restart/execute`.

A module file can also be changed on disk. AI Object Matching and Calibration read their module file again on `reset`; otherwise a change applies at the next start.

## Template Finder, Object Finder, Area Detector, Text Reader: modules at run time {#registry-apps}

Their modules are made and removed while the app runs.

| Node | Kind | What it does |
| --- | --- | --- |
| `system/modules` | string[], read-only | the modules now |
| `system/create-module/execute` | method, input `input/module-id` | a new module with default inputs, at once. Gone after a restart unless saved |
| `system/remove-module/execute` | method, input `input/module-id` | removes the module |
| `system/save-current-modules/execute` | method | writes the module list into the application file, and deletes the input files of modules no longer in it |
| `system/save-module-inputs/execute` | method, input `input/module-id` | writes the module’s inputs to `<module-id>.json`, restored at the next start |

Each finder adds its own functions, for example Template Finder `system/create-template` and `system/set-template-dir`, Text Reader `system/set-tessdata-dir` and `system/refresh-languages`. See the app’s manual.

Note that `create-module` means two different things: in the settings-file apps a file applied at the next restart, in the finders a live module lost at the next restart unless saved.

## What is kept across a restart {#kept}

| What | Kept |
| --- | --- |
| A finder module’s inputs | when saved with `system/save-module-inputs/execute`; restored at start |
| A finder app’s module list | when saved with `system/save-current-modules/execute` |
| Settings of the Cam Driver, AI Object Matching and Calibration written to `system/settings` | yes, applied at the next start |
| Folders chosen at run time (template, object and tessdata folders) | yes, saved automatically in the application file |
| A consumer’s stream | yes, see [Streams](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html#saved) |
| The Cam Driver’s stream and the camera connection | **no**: start them again after every start |
| Values written to `input/` of the Cam Driver, AI Object Matching and Calibration | **no**: write them again |

There is no load method: nothing reads a saved file again without a restart, except the `reset` of AI Object Matching and Calibration.

# Tools – LumiScan Keryx

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/tools.html

| Tool | Data Layer | For |
| --- | --- | --- |
| [Keryx page](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/tools.html#data-layer-page) | LumiScan Keryx, Windows | browsing the tree, reading, writing, calling methods, watching values |
| [LumiScan Keryx Utilities](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/tools.html#utilities) | LumiScan Keryx, Windows | subscribing to nodes and following stream results through the chain |
| [krxclient](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/tools.html#krxclient) | LumiScan Keryx | browsing, reading, writing and calling methods from the command line, in scripts and tests |
| [the ctrlX OS web interface](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/tools.html#ctrlx-web-interface) | ctrlX Data Layer | browsing, reading, writing and calling methods on ctrlX OS |

## The Keryx page {#data-layer-page}

`http://127.0.0.1:7555/` for the default broker - the broker’s port + 2000. Starting **LumiScan Keryx** opens the same page in a window. See [LumiScan Keryx on a PC](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html#data-layer-page).

## LumiScan Keryx Utilities {#utilities}

A window onto a broker: choose the broker, search its nodes, subscribe to the ones you want, and read what they publish in one list. It is a client only: it provides no nodes and changes nothing on the broker. Windows only.

1. Start it. A window opens; it needs the Microsoft Edge WebView2 Runtime, which Windows 11 includes. Without it the page opens in the default browser.
2. **Broker**: enter host and port (`127.0.0.1` and `5555` by default) and click **Connect**. The dot shows whether the broker answers.
3. **Add**: type words of an address in the search box, for example `camera1 stream frame`, and pick a node. An address the broker does not know yet can be added as typed: a subscription may come before its provider.
4. **Start** and **stop** each subscription with its own button. After a restart, and after a change of broker, subscriptions come back stopped - a camera stream is tens of megabytes per second. **Resume on start** changes that.
5. **Results**: one list, newest first, each row naming its source. **Keep newest** sets how many are kept.
6. **Follow an item**: click a row. For a stream result the detail lists every row about the same item, in the order it arrived and how long after the first, and the producers it passed with each one’s time. It never shows the pixels of a frame.

| What | Where |
| --- | --- |
| Subscriptions and settings | `%APPDATA%\LumiScan Keryx Utilities\settings.json` |
| Log | `%LOCALAPPDATA%\LumiScan Keryx Utilities\logs\keryx-utilities.log` |

The results are kept in memory only. `lost` counts updates the broker numbered that did not arrive.

## krxclient {#krxclient}

The command line client of LumiScan Keryx. It stands in for a PLC: `read`, `write`, `browse`, `metadata`, `tree`, `execute`, `subscribe`, and `handshake`, which runs a ready/request handshake. Give it the broker with `--keryx-backend` and `--keryx-url`, or with the environment variables `HDV_KERYX_BACKEND` and `HDV_KERYX_URL`.

```none
krxclient write hdvisionsystems/lumiscan-template-finder/module-1/control/subscribe/input/address hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream
krxclient write hdvisionsystems/lumiscan-template-finder/module-1/control/subscribe/input/enable true
krxclient execute hdvisionsystems/lumiscan-template-finder/module-1/control/subscribe/execute
krxclient subscribe hdvisionsystems/lumiscan-template-finder/module-1/control/subscribe/output/stream/result --count 5
```

`krxclient subscribe` shows a FlatBuffers value by its size only: it tells you that results arrive, not what they hold.

## The ctrlX OS web interface {#ctrlx-web-interface}

On ctrlX OS, open **Settings > Data Layer** in the ctrlX OS web interface. It shows the tree of the ctrlX Data Layer: browse to `hdvisionsystems/<app>`, read and write values, and call methods. See [ctrlX Data Layer on ctrlX OS](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/ctrlx-data-layer.html).

# OPC UA Connector – LumiScan Keryx

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/opc-ua.html

> [!NOTE]
> On ctrlX OS this connector is not used: a ctrlX PLC on the same device uses the nodes directly, see [Connecting a PLC](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/ctrlx-data-layer.html#connecting-a-plc).

The **LumiScan OPC UA Connector** (`lumiscan_opcua_connector`) shows the tree of LumiScan Keryx as an OPC UA address space. A PLC, a SCADA system or any OPC UA client reads, writes, calls and subscribes to the nodes of the apps without a Data Layer client of its own. The connector forwards every request to the Data Layer when it arrives; it stores no values of its own.

The address space is the Data Layer’s own tree, not an OPC UA companion specification such as OPC 40100 (Machine Vision).

## Endpoint and address space {#endpoint}

|   |   |
| --- | --- |
| Endpoint | `opc.tcp://<pc>:4840`, on every network interface of the PC |
| Security | security policy **None**, **anonymous** login, see [Security](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/opc-ua.html#security) |
| Namespace URI | `urn:hdvisionsystems:keryx` |
| NodeId | the Data Layer address as a string identifier in that namespace: `ns=<n>;s=hdvisionsystems/lumiscan-cam-driver/camera1/control/status/code` |
| BrowseName | the last segment of the address, for example `code` |
| Root | one object under `Objects`, called `Keryx`, that holds `hdvisionsystems` and the other top-level folders. Started with `--root hdvisionsystems` it is `hdvisionsystems`; the NodeIds stay the same |

**Find the namespace index `n` from the URI** in the server’s `NamespaceArray`. Do not write a fixed index into your program: another start can number it differently.

| Data Layer | OPC UA node |
| --- | --- |
| folder | Object (FolderType) |
| value | Variable (BaseDataVariableType), with the access the node allows |
| method | Method with **no input arguments** and one output argument `Result`, belonging to the object of its parent address |

The connector walks the tree at start and again every 2 seconds. An app that starts later, a module that is added and a node that disappears show up within about 2 seconds. There are no model change events: a client that cached its browse result must browse again. An app that stops keeps its nodes in the tree; reading them answers `BadTimeout`, then `BadNoCommunication`, until the app registers again.

## Starting the connector {#starting}

The installer adds a Start menu shortcut that starts the connector without options: port 4840, the whole Data Layer, anonymous, read and write.

**Start it after the apps.** The connector never starts a broker: without one it logs the reason and ends with exit code 1, and its window closes. Stop it with Ctrl+C. Like the apps it is protected with CodeMeter, see [LumiScan Licensing](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/index.html).

| Option | Meaning |
| --- | --- |
| `-p`, `--port <n>` | OPC UA port, default 4840 |
| `-r`, `--root <address>` | show only this subtree, for example `hdvisionsystems` |
| `--read-only` | refuse writes (`BadNotWritable`) and method calls (`BadNotExecutable`) |
| `--keryx-url <url>` | the broker, default `tcp://127.0.0.1:5555` |
| `--request-timeout-ms <ms>` | how long a read or write may take, default 2000 |
| `--method-timeout-ms <ms>` | how long a method call may take, default 60000 |
| `--method-workers <n>` | method calls that run at the same time, default 4 |
| `--min-publishing-ms <ms>` | the fastest a subscription sends notifications, default 10 |
| `--resync-ms <ms>` | how often the tree is walked again, default 2000 |
| `--sampling-ms <ms>` | sampled mode instead of event mode; not recommended |

`lumiscan_opcua_connector --help` lists all options.

## Security {#security}

**There is none.** The connector accepts any client, anonymous and unencrypted, and the client can write every writable node and call every method - including starting and stopping the camera and changing settings through `system/settings`. Treat it like an unprotected field-bus port:

- run it on a network you trust, such as the machine network between the PC and the PLC;
- open TCP 4840 in the PC’s firewall for the PLC’s address only;
- for a client that only observes, run a second instance read-only on its own port: `lumiscan_opcua_connector --root hdvisionsystems --port 4841 --read-only`.

Certificates, user names and encryption are not supported; a client that insists on a secure channel cannot connect.

## Reading, writing and types {#types}

**The type must be exactly the node’s.** The connector does not convert: a `Boolean` node takes a Boolean, not 0 or 1; a `UInt32` node takes UInt32, not Int32. Most trouble with a first connection is a type that is one size off.

| Node type | OPC UA type | IEC 61131-3 |
| --- | --- | --- |
| bool | Boolean | `BOOL` |
| int32 | Int32 | `DINT` |
| uint32 | UInt32 | `UDINT` |
| uint64 | UInt64 | `ULINT` |
| float32 | Float | `REAL` |
| float64 | Double | `LREAL` |
| string | String | `STRING` |
| arrays of these | the same type, one dimension | `ARRAY [..] OF …` |
| FlatBuffers result, image | ByteString | not usable without a decoder |

- A read waits up to 2 seconds. A node that did not answer is `BadNoCommunication` for the next 5 seconds.
- A write replaces the whole value and is never repeated. A write with a `NumericRange` is refused (`BadWriteNotSupported`).
- The timestamps of a value are the connector’s: the Data Layer carries no time of its own.
- Do not build PLC logic on FlatBuffers values. Use the plain nodes beside them.

## Calling the three patterns {#calls}

**Handshake**: only reads and writes, as in [Handshake](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/handshake.html). Poll at 50 to 100 ms.

**Execute**: write the method’s inputs - a method has no arguments, its inputs are separate nodes - then use the **Call** service with `objectId` = the parent address (for example `…/camera1/control/trigger`) and `methodId` = the method (`…/camera1/control/trigger/execute`). The call answers when the method has finished, after up to 60 seconds; set your client’s call timeout higher than your slowest method. The status of the call says whether the operation could run, see [Results of a method call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#method-results). Then read `control/status/code` and the outputs.

**Stream**: subscribe to the result node, see [Subscriptions](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/opc-ua.html#subscriptions).

## Subscriptions {#subscriptions}

Create a subscription and add a monitored item for the node:

| Setting | Value | Why |
| --- | --- | --- |
| Publishing interval | 10 ms or more | the server’s fastest |
| Sampling interval | **0** | reports every push as it arrives (event mode) |
| Queue size | 10 to 100 | with 1 only the newest push arrives |
| DataChange trigger | `StatusValueTimestamp` | otherwise two identical results count as one |
| DiscardOldest | true |   |

- A node reports a change when the app pushes it; streams do. A value too large to be pushed never reports in event mode: use a positive sampling interval for it.
- Large values cost: a 1.5 MB camera frame sampled every 10 ms is 150 MB/s for one item. Do not monitor `output/image`, `…/stream/frame` or `…/stream/result` unless you decode them. For coordinates, monitor Calibration’s `plain-points`.
- At start the connector checks that event mode works. If it does not, it logs that and samples every item on a timer (sampled mode). If your client gets fewer notifications than pushes, read the connector’s log first.

## OPC UA status codes {#status}

Beyond the results of a method call:

| Status | Meaning |
| --- | --- |
| `BadNodeIdUnknown` | wrong address, case or namespace index; the app is not running; the module is missing |
| `BadNoCommunication` | the app has stopped or hangs |
| `BadTimeout` | the app did not answer in 2 s (read, write) or 60 s (call) |
| `BadTypeMismatch` | the value is not of the node’s type |
| `BadWriteNotSupported` | a write with a `NumericRange` |
| `BadNotWritable` | an output, or the connector is read-only |
| `BadNotExecutable` | the connector is read-only |
| `BadMethodInvalid` | the node is no longer a method of the tree: browse again |

After an app has restarted, run your start-up sequence again: the camera is not connected and the Cam Driver’s stream is off. If a monitored item does not report again, delete and create it.

# FAQ – LumiScan Keryx

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/faq.html

Short answers to common questions about the Data Layer. Each entry links to the page with the details. Problems and error messages are described in [Troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html).

> [!TIP]
> Each entry has a fixed anchor (for example `#faq-start-broker`). To find an error message, search the [Troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html) page for it.

## Platforms and broker

### Do I have to change my program when I move from ctrlX OS to a PC? {#faq-same-interface}

- **Answer:** No, not the node addresses, types or call patterns: they are the same on the ctrlX Data Layer and LumiScan Keryx. What changes is the connection (a PLC on ctrlX OS, the OPC UA Connector on a PC), the tools, and the names of the method results.
- **More:** [ctrlX Data Layer and LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/platforms.html)

### Do I have to start the broker on a PC? {#faq-start-broker}

- **Answer:** No. When an app starts and no broker answers on the PC, it starts one at `tcp://127.0.0.1:5555`. The broker keeps running when the apps end. Only the OPC UA Connector never starts one: start it after the apps.
- **More:** [The broker](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html#broker)

### How do I look at the nodes? {#faq-see-nodes}

- **Answer:** On Windows on the Keryx page `http://127.0.0.1:7555/`, in **LumiScan Keryx Utilities**, or with `krxclient`. On Ubuntu with `krxclient`. On ctrlX OS in the Data Layer view of the ctrlX OS web interface.
- **More:** [Tools](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/tools.html)

## Calling functions

### Should I use the handshake or the execute method? {#faq-handshake-or-execute}

- **Answer:** Use the execute method for operations within about 1 s when your program can wait. Use the handshake for longer operations - the Cam Driver’s `connect-camera`, `disconnect-camera` and `reset` are handshakes only - or when your program must not block. Use a stream for continuous processing.
- **More:** [Choosing a Pattern](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/calling-functions.html)

## Streams

### How does a PLC read stream results? {#faq-stream-plc}

- **Answer:** Stream results are FlatBuffers records. Switch on `keep-latest-output` in the module whose result you need and read its plain output nodes, or subscribe to Calibration’s `plain-points`.
- **More:** [Keep latest output](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html#keep-latest)

## OPC UA

### Can the OPC UA Connector use encryption or user names? {#faq-opcua-security}

- **Answer:** No. It accepts anonymous, unencrypted clients only. Run it on a trusted machine network, open port 4840 for the PLC only, and give observing clients a `--read-only` instance.
- **More:** [Security](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/opc-ua.html#security)

## Troubleshooting {#troubleshooting}

Problems and error messages are described step by step in [Troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html):

- [An app waits for the broker (PC)](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#no-broker)
- [An app or a module is missing from the tree](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#app-missing)
- [A node is "not found"](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#node-not-found)
- [A method call is refused](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#refused)
- [Status `-5` (`restartRequired`), or `ResourceUnavailable` on every call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#faq-restart-required)
- [The execute call answers `Ok` (`DL_OK`), but nothing happened](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#faq-write-ok-but-failed)
- [A handshake does not finish, or shows the wrong outcome](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#handshake-stuck)
- [A stream delivers nothing](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#stream-nothing)
- [Stream results are old or mixed](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#ts-stream-results-mixed)
- [An OPC UA client cannot connect](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#ts-opcua-cannot-connect)
- [The connector window closes at once](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#ts-opcua-window-closes)
- [`Objects` is empty or has no `hdvisionsystems`](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#ts-opcua-objects-empty)
- [`BadNodeIdUnknown`](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#ts-opcua-bad-node-id)
- [`BadTypeMismatch` on a write](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#faq-opcua-type-mismatch)
- [A subscription gets only one value, or misses results](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#ts-opcua-subscription)
- [Notifications stop after the connector or an app restarts](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#ts-opcua-notifications-stop)

## Support

### Where do I get help? {#faq-support}

- **Answer:** See the site-wide [LumiScan FAQ](https://docs.hdvisionsystems.com/en/faq.html), or contact [customer.success@hdvisionsystems.com](mailto:customer.success@hdvisionsystems.com), +49 6221 6721905. For licences: [licenses@hdvisionsystems.com](mailto:licenses@hdvisionsystems.com).

# Troubleshooting – LumiScan Keryx

URL: https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html

Start with the [General checks](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#general-checks): they help with every Data Layer problem. Then find your symptom in the sections below and work through its steps in order. The last section lists what to send to support if the problem persists.

## General checks {#general-checks}

Check these points first:

- **The app runs and is on the Data Layer.** On a PC, open the Keryx page `http://127.0.0.1:7555/` (Windows) or run `krxclient tree hdvisionsystems --depth 1`: the tree shows the folder `hdvisionsystems` with one folder per running app. On ctrlX OS, use the Data Layer view of the ctrlX OS web interface. See [Tools](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/tools.html).

- **All programs use the same broker (PC).** Each app names the broker address it uses in its log at start. Every app, Cockpit and the OPC UA Connector must use the same address. The default is `tcp://127.0.0.1:5555`; `--keryx-url` or `LUMISCAN_KERYX_URL` changes it. See [Options and environment variables](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html#options).

- **The app serves its modules.** For each app that has modules, `hdvisionsystems/<app>/system/found-modules` lists them. If the list is empty, `hdvisionsystems/<app>/system/status-text` says why.

- **The status of the module.** The Cam Driver, AI Object Matching and Calibration report it on `<module>/control/status/code` and `control/status/text`: values below `0` are errors. The finders report each method on `<method>/output/status-code` and `status-text`. Use the numbers, not the texts. See [Status Codes and Results](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html).

- **The addresses match the app version.** Addresses are lower case. Several nodes moved in the upcoming releases without an alias at the old address: compare your program with the **Data Layer Reference** of the app version you run.

- **The logs.** The apps log the first refusal of a method, then at most one line every ten seconds for the same method and result.

  | Log | Where |
  | --- | --- |
  | An app on ctrlX OS | the ctrlX OS system log: the Logbook of the ctrlX web interface, or `journalctl` |
  | The broker on Windows (log, records and `broker.json`) | `C:\ProgramData\HD Vision Systems GmbH\LumiScan Keryx` |
  | The broker on Ubuntu | `/tmp/lumiscan-keryx` |
  | LumiScan Keryx Utilities | `%LOCALAPPDATA%\LumiScan Keryx Utilities\logs\keryx-utilities.log` |

## Broker, apps and nodes {#broker-apps-nodes}

### Problem: An app waits for the broker (PC) {#no-broker}

**Symptoms**

An app on a PC logs that it could not reach a Data Layer broker (`could not reach a Keryx broker`), and waits.

**Possible causes**

- It is the first start: the broker takes a few seconds to answer.
- **LumiScan Keryx** is not installed.
- The terminal was opened before LumiScan Keryx was installed. The installer sets the variables `HDV_KERYX_BROKER` and `HDV_KERYX_PAGE`; a program or terminal that was already open does not see them.
- The automatic start is switched off: `--no-keryx-autostart` or `LUMISCAN_KERYX_AUTOSTART=0`.
- The broker was stopped with **Shut down broker** on the Keryx page.
- The address is an `ipc://` address relative to a folder: no app starts a broker for it.
- The address is that of another computer: an app only connects to it and never starts a broker there.

**Diagnostic procedure**

1. Wait a few seconds after the first start - expected: the app connects as soon as the broker answers.
2. Read the broker address in the app’s log at start - expected: the address you intend to use, by default `tcp://127.0.0.1:5555`.
3. Check that LumiScan Keryx is installed, and that you opened the terminal after its installation.
4. Check the options and environment variables of the app - expected: neither `--no-keryx-autostart` nor `LUMISCAN_KERYX_AUTOSTART=0` is set, unless you start the broker yourself.
5. Check whether someone clicked **Shut down broker** on the Keryx page. After that, the apps do not start the broker again by themselves.
6. With an `ipc://` address: check that the broker and every app were started from the same folder.

**Resolution**

- **If it is the first start:** wait. The app connects as soon as the broker answers.

- **If LumiScan Keryx is not installed:**

  a. Install LumiScan Keryx first, then the apps. Run each installer as administrator.

  b. Open a **new** terminal and start the app again.

- **If the terminal was opened before the installation:** open a new terminal and start the app again.

- **If the automatic start is switched off:** remove the option or the variable, or start the broker yourself: `krxsystem --backend hdv --url <address>`.

- **If the broker was shut down:** click **Start broker** on the Keryx page, or open the LumiScan Keryx window. Starting a `krxsystem` by hand or restarting the PC also starts it again.

- **If the address is a relative `ipc://` address:** start the broker yourself (`krxsystem --backend hdv --url <address>`), then start every app from that same folder.

- **If the address is that of another computer:** running apps on several PCs against one broker is not covered by this manual. Contact support.

See [LumiScan Keryx on a PC](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the message from the app’s log, the broker address the app names there, and the broker log.

### Problem: An app or a module is missing from the tree {#app-missing}

**Symptoms**

The tree has no folder for the app under `hdvisionsystems`, or a module you expect does not appear on the Data Layer: `hdvisionsystems/<app>/system/found-modules` does not list it.

**Possible causes**

- The app is not running.
- The app uses another broker than the program you look with (PC).
- The settings file could not be loaded.
- The licence is missing. On ctrlX OS, an app without a valid licence stops shortly after it starts.
- The module name contains capital letters or other characters than `a-z`, `0-9`, `-` and `_`. The Cam Driver and AI Object Matching refuse such a module.
- Cam Driver, AI Object Matching, Calibration: the module file was activated with `system/control/activate-module/execute`, but the app has not restarted since.
- Template Finder, Object Finder, Area Detector, Text Reader: the module was made with `system/create-module/execute` and not saved, and the app has restarted since.

**Diagnostic procedure**

1. Check the tree - on a PC on the Keryx page or with `krxclient tree`; on ctrlX OS in the ctrlX OS web interface; expected: the folder `hdvisionsystems` holds one folder per running app.
2. On a PC, compare the broker address in the app’s log with the address of Cockpit, the OPC UA Connector or the tool you use - expected: the same address.
3. Read `hdvisionsystems/<app>/system/found-modules` - expected: it lists the module.
4. If it does not, read `hdvisionsystems/<app>/system/status-text` - expected: it says why the app serves no module, most often a settings file that could not be loaded, or a missing licence.
5. Check the module name - expected: only lower-case letters, digits, `-` and `_`. The name comes from `id` in the module file (Cam Driver), from `name` in the module file (AI Object Matching), from the module file’s name (Calibration), or from the module id (the finders). See [Module names](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/addresses.html#module-names).
6. On ctrlX OS, read the system log - expected: no message that the licence is missing.

**Resolution**

- **If the app is not running:** start it, and wait until it has finished starting.

- **If the app uses another broker:** pass the same `--keryx-url` to every app, to Cockpit and to the OPC UA Connector.

- **If the settings file could not be loaded:** correct it, and start the app again. On a PC, the settings are files in the app’s settings folder (on Windows `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\<program>\etc\<settings folder>`); the option `--generate-settings` writes an example. See [Where the files are](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html#files). On ctrlX OS, upload them as the app’s manual describes under **Uploading Data**.

- **If the licence is missing:** see [LumiScan Licensing](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/index.html).

- **If the module name is not valid:** use lower-case module names.

- **If the app has not restarted since the activation:** call `hdvisionsystems/<app>/system/control/restart/execute`.

- **If a finder module was not saved:**

  a. Make the module again with `system/create-module/execute`.

  b. Save the module list with `system/save-current-modules/execute` and the module’s inputs with `system/save-module-inputs/execute`.

See [Settings, Modules and Restart](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/settings-and-modules.html).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the content of `system/found-modules` and `system/status-text`, and the module file.

### Problem: A node is "not found" {#node-not-found}

**Symptoms**

A read, write or call answers that the node was not found: `NodeNotFound` (LumiScan Keryx), `DL_INVALID_ADDRESS` (ctrlX Data Layer) or `BadNodeIdUnknown` (OPC UA). A program written for an earlier release no longer finds a node it used.

**Possible causes**

- The case or spelling of the address is wrong. Addresses are lower case.
- The node moved. Several nodes moved in the upcoming releases without an alias at the old address, for example the Cam Driver’s stream from `input/stream/enable` to `control/publish/input/enable`.
- The app is restarting: its nodes disappear until it is up again.
- The module is missing, see [Problem: An app or a module is missing from the tree](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#app-missing).

**Diagnostic procedure**

1. Compare the address with the tree - on a PC on the Keryx page or from `krxclient tree`; on ctrlX OS in the ctrlX OS web interface; expected: the same case and spelling.
2. Compare the address with the **Data Layer Reference** of the app version you run - expected: the node is listed there at this address.
3. Check whether the app is restarting - expected: `system/restart-required` can be read.

**Resolution**

- **If the case or spelling is wrong:** correct the address.
- **If the node moved:** change your program to the address in the **Data Layer Reference** of the app version you run.
- **If the app is restarting:** wait until `system/restart-required` can be read again.
- **If the module is missing:** see [Problem: An app or a module is missing from the tree](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#app-missing).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the address that is not found and the result of the call.

## Calling functions {#calling-functions}

### Problem: A method call is refused {#refused}

**Symptoms**

A write to an `execute` node does not answer `Ok` (`DL_OK`, OPC UA `Good`), but one of the results in [Results of a method call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#method-results), for example `TooManyOperations`, `InvalidOperationMode`, `ResourceUnavailable` or `Rejected`. On the ctrlX Data Layer, a refused call carries no reason.

**Possible causes**

- `TooManyOperations` (ctrlX `DL_TOO_MANY_OPERATIONS`, OPC UA `BadTooManyOperations`): another operation of the same module runs - an execute, a handshake, or in the finders a frame of a stream.
- `InvalidOperationMode` (ctrlX `DL_INVALID_OPERATION_MODE`, OPC UA `BadInvalidState`): the function is not ready. Its `ready` is `false`, for example because there is no licence, the camera is not connected, or a stream runs.
- `ResourceUnavailable` (ctrlX `DL_RESOURCE_UNAVAILABLE`, OPC UA `BadResourceUnavailable`): a restart is required after a change through `system/settings` (status `-5`), the app is stopping, or an AI module is in error.
- `Rejected` (ctrlX `DL_INVALID_VALUE`, OPC UA `BadRequestNotAllowed`): an input is not valid; nothing changed.
- `NodeNotFound` (ctrlX `DL_INVALID_ADDRESS`, OPC UA `BadNodeIdUnknown`): an image, a source, a module or the node itself was not found.
- `CreationFailed` (ctrlX `DL_CREATION_FAILED`): something could not be written or made, for example a file, an existing module or an unavailable licence.
- `InternalError` (ctrlX `DL_FAILED`, OPC UA `BadInternalError`): the operation failed.

**Diagnostic procedure**

1. Note the result of the call, and look it up in [Results of a method call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#method-results).
2. Read the app’s log - expected: the reason of the refusal. The apps write it there because a refused call on the ctrlX Data Layer carries none.
3. Cam Driver, AI Object Matching, Calibration: read `control/<function>/ready` together with `control/status/code` and `control/status/text`. `ready` names the missing precondition; the status text still carries the message of the fault that caused it.
4. Finders: read `<method>/output/status-code` and `status-text`. See [Execution status of the finders](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#execution-status).

**Resolution**

- **If another operation of the module runs (`TooManyOperations`):** retry. The same call succeeds once the running operation has finished.
- **If the function is not ready (`InvalidOperationMode`):** bring the module into the required state first, for example connect the camera. Retrying alone keeps failing: do not retry in a loop. The Cam Driver’s `capture` and AI Object Matching’s `inference` are not ready while their stream runs: stop the stream first, see [Streams and single operations](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html#collisions). The app’s manual says when each `ready` is `true`.
- **If a restart is required (`ResourceUnavailable`, status `-5`):** see [Problem: Status `-5` (`restartRequired`), or `ResourceUnavailable` on every call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#faq-restart-required).
- **If the app is stopping or an AI module is in error (`ResourceUnavailable`):** read the status, and restart the app when required.
- **If an input is not valid (`Rejected`):** correct the input and call again.
- **If something was not found (`NodeNotFound`):** check the address and its case, see [Problem: A node is "not found"](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#node-not-found).
- **If something could not be written or made (`CreationFailed`), or the operation failed (`InternalError`):** read the log and the status; they say why.

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the address of the method, its result, the values of `ready`, `control/status/code` and `control/status/text`, and the log lines about the refusal.

### Problem: Status `-5` (`restartRequired`), or `ResourceUnavailable` on every call {#faq-restart-required}

**Symptoms**

Every module of the app reports `control/status/code` = `-5` (`restartRequired`), and its methods answer `ResourceUnavailable` (ctrlX `DL_RESOURCE_UNAVAILABLE`, OPC UA `BadResourceUnavailable`).

**Possible causes**

- The settings were changed through `system/settings`. They apply at the next start.

**Diagnostic procedure**

1. Read `hdvisionsystems/<app>/system/restart-required` - expected after a saved change: `true`, until the app restarts.

**Resolution**

- **If the settings were changed through `system/settings`:**

  a. Call `hdvisionsystems/<app>/system/control/restart/execute`. The app’s nodes disappear until it is up.

  b. Wait until `system/restart-required` can be read again.

  c. Run your start-up sequence again: values written to `input/` are not kept, the camera is not connected, and the Cam Driver’s stream is off. See [What is kept across a restart](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/settings-and-modules.html#kept).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the value of `system/restart-required` and the content of `system/settings`.

### Problem: The execute call answers `Ok` (`DL_OK`), but nothing happened {#faq-write-ok-but-failed}

**Symptoms**

Cam Driver, AI Object Matching, Calibration: a write to an `execute` node answers `Ok` (`DL_OK`, OPC UA `Good`), but the operation had no effect.

**Possible causes**

- The operation ran but failed. The result of the write only says that the operation ran. Whether it succeeded is in the module status.

**Diagnostic procedure**

1. Read `control/status/code` and `control/status/text` right after the call - expected: `0` (`ready`). Values below `0` are errors.
2. Look up the code in [Module status](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#module-status). App-specific codes are listed in each app’s manual.

**Resolution**

- **If the status is below `0`:** remove the cause the code names, for example correct an input (`-3`, `invalidInput`), or restart the app (`-5`, see [Problem: Status `-5` (`restartRequired`), or `ResourceUnavailable` on every call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#faq-restart-required)). Then call again.
- In your program, always read `control/status/code` after the call. See [Where the inputs, outputs and outcome are](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/execute.html#where).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the address of the method and the values of `control/status/code` and `control/status/text` after the call.

### Problem: A handshake does not finish, or shows the wrong outcome {#handshake-stuck}

**Symptoms**

`ready` stays `false` after the request; a Cam Driver `capture` or an AI Object Matching `inference` by handshake ends at status `3` (`waitingForClient`); or a failed Cam Driver `connect-camera` shows its error for about 100 ms only.

**Possible causes**

- `request` is still `true`: the module waits for `request` to fall, for as long as it takes.
- Two programs write the same `request` node, and a request is lost.
- Cam Driver `capture`: a failed capture ends at status `3`, not at its own error code, and `capture/ready` stays `false` until a `reset` succeeds. A failed `reset`, `save` or `load` also stays until a `reset` succeeds.
- AI Object Matching `inference`: every inference ends at status `3` whatever its outcome. After a failed inference, and while the module has an error, every request but `reset` is ignored. While the stream runs, `inference/ready` is `false` and a request gets status `100002`.
- Cam Driver: any other error stays on the status for about 100 ms only.
- Cam Driver without a licence: every `ready` is `false` and the status is `-4`.

**Diagnostic procedure**

1. Follow the steps in [The sequence](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/handshake.html#sequence), polling at 50 to 100 ms, and note the step at which it stops.
2. Read `request` after `ready` has become `false` - expected: your program has set it back to `false`.
3. Check which programs write the `request` node - expected: only one.
4. For a Cam Driver `capture` or an AI Object Matching `inference`: read `output/package-identifier` before and after - expected: it has grown by one when the operation succeeded.
5. For a Cam Driver `connect-camera`: read `device-info/is-connected` - expected: `true` when the camera is connected.
6. For the Cam Driver: read `control/status/code` - expected: not `-4`.

**Resolution**

- **If `request` is still `true`:** set `request` to `false`.
- **If two programs write `request`:** let only one program write it. A program that cannot coordinate with others uses the [execute method](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/execute.html), which refuses a second call while one runs.
- **If a `capture` or an `inference` ends at status `3`:** this is how they end. Use `output/package-identifier` to tell success, or use the execute method: the status then keeps the operation’s own code. After a failed capture, run `reset`.
- **If AI Object Matching ignores requests after a failed inference:** run `reset`; it runs at once.
- **If the AI Object Matching stream runs (status `100002`):** stop the stream first.
- **If a Cam Driver error disappears from the status after about 100 ms:** check a connection with `device-info/is-connected`, not with the status.
- **If the Cam Driver has no licence (status `-4`):** see [LumiScan Licensing](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/index.html).

See [How the apps differ](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/handshake.html#differences).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the function, the step at which the handshake stops, and the values of `ready`, `request`, `control/status/code` and `output/package-identifier`.

## Streams {#streams}

### Problem: A stream delivers nothing {#stream-nothing}

**Symptoms**

No results arrive from a stream: `output/stream/active` stays `false`, or the counters under `…/stream/statistics/` stop growing. After a restart no images arrive.

**Possible causes**

- The inputs were written, but `execute` was not called. The inputs take effect only on `execute`; writing `enable` alone starts nothing.
- `enable` is `true` without an address. The call is refused (`Rejected`, ctrlX `DL_INVALID_VALUE`), and nothing changes.
- The consumer’s `address` is not the producer’s stream folder.
- The module cannot run: licence, network not loaded, or restart required.
- The Cam Driver restarted: its stream and the camera connection are not kept across a restart.
- `connect-camera`, `disconnect-camera` or `reset` stopped the Cam Driver’s stream.
- Nothing triggers the camera. The Cam Driver never triggers the camera by itself.
- Calibration: its `stream` section has no `onEntry` step that says how to read the source.

**Diagnostic procedure**

1. On the camera, read `control/publish/output/stream/active` - expected: `true`.

2. On the consumer, read `control/subscribe/output/stream/active` - expected: `true`.

3. On the consumer, read `setting/stream/…` - expected: `enable` is `true`, and `address` is the producer’s stream folder, for example `hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream`.

4. Follow the chain with the counters under `…/stream/statistics/` - expected: they grow. The first counter that does not grow shows where the chain stops. See [Following the chain](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html#counters).

   a. The Cam Driver counts no `frames`: nothing triggers the camera.

   b. Calibration: `failed-updates` grows and no points appear: the `onEntry` step is missing.

   c. Finders and code readers: `control/subscribe/output/stream/last-failure` says why the last item failed.

5. Read `control/status/code` and the log of the module that stops the chain.

**Resolution**

- **If `execute` was not called:** after writing the inputs, call `control/subscribe/execute` (a consumer) or `control/publish/execute` (the Cam Driver). Then wait until `output/stream/active` is `true`.

- **If `enable` is `true` without an address:** write `control/subscribe/input/address`, then call `control/subscribe/execute`.

- **If the address is not the producer’s stream folder:** write the folder, for example `hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream`, and call `execute`.

- **If the module cannot run:** remove the cause that `control/status/code` and the log name. For a required restart, see [Problem: Status `-5` (`restartRequired`), or `ResourceUnavailable` on every call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#faq-restart-required).

- **If the Cam Driver restarted, or the stream was stopped by `connect-camera`, `disconnect-camera` or `reset`:**

  a. Run the `connect-camera` handshake.

  b. Call `control/publish/execute` with `enable` = `true`.

  c. The consumers subscribe again by themselves.

- **If nothing triggers the camera:** check its trigger mode, or call `control/trigger/execute`.

- **If the Calibration `onEntry` step is missing:** add it to the `stream` section. See the Calibration manual.

See [Starting and stopping a stream](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html#running).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the values of `output/stream/active`, `setting/stream/…` and the counters under `…/stream/statistics/` of every module in the chain.

### Problem: Stream results are old or mixed {#ts-stream-results-mixed}

**Symptoms**

The results your program reads are old, or values of different results are mixed.

**Possible causes**

- Your program read while a new result was written.

**Diagnostic procedure**

1. Check how your program reads the plain output nodes - expected: it reads them after `output/package-identifier` has changed. `output/package-identifier` is written last.

**Resolution**

- **If your program reads while a new result is written:** read the outputs when `output/package-identifier` changes, or subscribe to a single node such as Calibration’s `plain-points`. See [Keep latest output](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html#keep-latest).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the nodes your program reads and in which order.

## OPC UA Connector {#opc-ua}

### Problem: An OPC UA client cannot connect {#ts-opcua-cannot-connect}

**Symptoms**

The client cannot connect to `opc.tcp://<pc>:4840`.

**Possible causes**

- The connector does not run: it was started before the broker and ended, see [Problem: The connector window closes at once](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#ts-opcua-window-closes).
- The PC’s firewall blocks TCP port 4840.
- The client insists on a secure channel. The connector supports security policy **None** and anonymous login only.
- The connector was started on another port (`--port`).

**Diagnostic procedure**

1. Check that the connector runs - expected: its window is open.
2. Check the PC’s firewall - expected: TCP 4840 is open for the address of the PLC or client.
3. Check the client’s security settings - expected: security policy **None**, anonymous login.
4. Check the connector’s options - expected: the port the client uses.

**Resolution**

- **If the connector does not run:** start the apps first, then the connector.
- **If the firewall blocks the port:** open TCP 4840 for the PLC’s address only.
- **If the client insists on a secure channel:** set it to security policy **None** and anonymous login. Certificates, user names and encryption are not supported. See [Security](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/opc-ua.html#security).
- **If the connector runs on another port:** connect to that port.

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the connector’s options, its log, and the error message of the client.

### Problem: The connector window closes at once {#ts-opcua-window-closes}

**Symptoms**

The window of the OPC UA Connector closes right after its start; the connector ends with exit code 1.

**Possible causes**

- No broker runs. The connector never starts a broker: without one it logs the reason and ends.
- The connector’s `--keryx-url` names another broker than the apps use.

**Diagnostic procedure**

1. Check that the apps run - expected: the Keryx page shows `hdvisionsystems` with the apps.
2. Compare `--keryx-url` of the connector with the broker address the apps name in their logs - expected: the same address.
3. Read the connector’s log - expected: the reason why it ended.

**Resolution**

- **If no broker runs:** start the apps first, then the connector.
- **If the connector uses another address:** pass it the same `--keryx-url` as the apps.

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the connector’s options and its log.

### Problem: `Objects` is empty or has no `hdvisionsystems` {#ts-opcua-objects-empty}

**Symptoms**

The client is connected, but `Objects` is empty or does not hold `hdvisionsystems`.

**Possible causes**

- The apps are not running.
- The connector’s `--keryx-url` names another broker than the apps use.
- An app started only recently: the connector walks the tree again every 2 seconds.

**Diagnostic procedure**

1. Check that the apps run - expected: the Keryx page shows `hdvisionsystems` with the apps.
2. Compare `--keryx-url` of the connector with the broker address the apps name in their logs - expected: the same address.
3. Browse again after about 2 seconds - expected: an app that started later shows up.

**Resolution**

- **If the apps are not running:** start them.
- **If the connector uses another address:** restart it with the same `--keryx-url` as the apps.
- **If an app started only recently:** browse again. There are no model change events: a client that cached its browse result must browse again.

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the connector’s options and its log.

### Problem: `BadNodeIdUnknown` {#ts-opcua-bad-node-id}

**Symptoms**

A read, write or call over OPC UA answers `BadNodeIdUnknown`.

**Possible causes**

- The address, its case or the namespace index is wrong.
- The app is not running.
- The module is missing.

**Diagnostic procedure**

1. Look up the namespace index `n` of the URI `urn:hdvisionsystems:keryx` in the server’s `NamespaceArray` - expected: the index your program uses.
2. Check the NodeId - expected: `ns=<n>;s=<address>`, with the Data Layer address in lower case, for example `ns=<n>;s=hdvisionsystems/lumiscan-cam-driver/camera1/control/status/code`.
3. Read `hdvisionsystems/<app>/system/found-modules` - expected: it lists the module.

**Resolution**

- **If the namespace index is wrong:** look it up by its URI after each connect. Do not write a fixed index into your program: another start can number it differently.
- **If the address is wrong:** correct case and spelling, see [Problem: A node is "not found"](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#node-not-found).
- **If the app is not running or the module is missing:** see [Problem: An app or a module is missing from the tree](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#app-missing).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the NodeId and the content of the server’s `NamespaceArray`.

### Problem: `BadTypeMismatch` on a write {#faq-opcua-type-mismatch}

**Symptoms**

A write over OPC UA answers `BadTypeMismatch`.

**Possible causes**

- The value’s type is not exactly the node’s type. The connector does not convert: a `Boolean` node takes a Boolean, not 0 or 1; a `UInt32` node takes UInt32, not Int32.

**Diagnostic procedure**

1. Look up the node’s type, for example on the Keryx page (select the node) - expected: the type your client sends, mapped as in [Reading, writing and types](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/opc-ua.html#types).

**Resolution**

- **If the type differs:** send exactly the node’s type, for example `Boolean` for flags and `UInt32` for `queue-size`.

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the address of the node and the type your client sends.

### Problem: A subscription gets only one value, or misses results {#ts-opcua-subscription}

**Symptoms**

A monitored item reports only one value, or fewer notifications than the app pushes.

**Possible causes**

- The monitored item’s settings differ from the recommended ones: sampling interval not `0`, a queue size of 1 (only the newest push arrives), or a DataChange trigger other than `StatusValueTimestamp` (two identical results count as one).
- The node does not push: a value too large to be pushed never reports in event mode.
- The connector found at start that event mode does not work, and samples every item on a timer.

**Diagnostic procedure**

1. Compare the subscription with [Subscriptions](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/opc-ua.html#subscriptions) - expected: publishing interval 10 ms or more, sampling interval `0`, queue size 10 to 100, DataChange trigger `StatusValueTimestamp`, DiscardOldest `true`.
2. Read the connector’s log first - expected: no message that it uses sampled mode.

**Resolution**

- **If the settings differ:** set them as recommended. Use sampling interval `0` only on nodes that push.
- **If the node does not push:** use a positive sampling interval for it.
- **If the connector uses sampled mode:** contact support with its log.

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the subscription settings and the connector’s log.

### Problem: Notifications stop after the connector or an app restarts {#ts-opcua-notifications-stop}

**Symptoms**

After the connector restarted, the client gets no notifications. After an app restarted, a monitored item does not report again, or reads answer `BadTimeout`, then `BadNoCommunication`.

**Possible causes**

- The connector restarted: the client’s subscriptions are gone.
- An app stopped or restarted. An app that stops keeps its nodes in the tree; reading them answers `BadTimeout`, then `BadNoCommunication`, until the app registers again. After the restart the camera is not connected and the Cam Driver’s stream is off.

**Diagnostic procedure**

1. Check whether the connector or an app restarted at the time the notifications stopped.
2. Read a node of the app - expected: a value, not `BadTimeout` or `BadNoCommunication`.

**Resolution**

- **If the connector restarted:** reconnect and create the subscriptions again.

- **If an app restarted:**

  a. Wait until the app has registered again.

  b. Run your start-up sequence again.

  c. If a monitored item does not report again, delete and create it.

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#support-information) to support, together with the time of the restart and the connector’s log.

## Information for support {#support-information}

If the problem persists, contact [customer.success@hdvisionsystems.com](mailto:customer.success@hdvisionsystems.com), +49 6221 6721905. For licences: [licenses@hdvisionsystems.com](mailto:licenses@hdvisionsystems.com). Please send:

- the app and its version;
- the platform: Windows 11, Ubuntu 24.04, or ctrlX OS and its version;
- the date and time of the error;
- the log of the app; on ctrlX OS from the system log (Logbook of the ctrlX web interface, or `journalctl`);
- on a PC, the broker log from `C:\ProgramData\HD Vision Systems GmbH\LumiScan Keryx` (Windows) or `/tmp/lumiscan-keryx` (Ubuntu), and, if you use them, the logs of the OPC UA Connector and of LumiScan Keryx Utilities;
- the communication status: the Data Layer address the apps use, the content of `system/found-modules` and `system/status-text`, the module status (`control/status/code` and `text`, or a finder’s `status-code` and `status-text`), the result of a refused call, and over OPC UA the status code and the connector’s options;
- the configuration: the settings files of the app (on a PC in `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\<program>\etc\<settings folder>`, on ctrlX OS in the app’s folder of `/var/snap/rexroth-solutions/common/solutions/activeConfiguration`), or the content of `system/settings`, and on a PC `broker.json`.
