# LumiScan QR Code Reader 1.0.0.5 – complete documentation

> All pages of the LumiScan QR Code Reader 1.0.0.5 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-qr-code-reader/1.0.0/

# Description – LumiScan QR Code Reader

URL: https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/description.html

LumiScan QR Code Reader finds QR codes in a camera image and reports, for each one, what it says and where it is.

It reads **QR** codes — the 2D symbology with a square finder pattern in three corners, the most widely used code for carrying a long payload such as a URL or a serial number. Every code found in the image is reported: there is no limit of one per run, and no reference picture or training step of any kind.

> [!NOTE]
> The application needs **no template and no configuration**. You give it the address of an image and call `execute`; it reads every QR code in that image. Its sibling applications read the other symbologies — LumiScan DMC Reader, LumiScan Aztec Code Reader and LumiScan Barcode Reader — and work the same way.

## Where the images come from

The application does not talk to a camera itself. It reads an image node published by another application on the Data Layer - the ctrlX Data Layer on ctrlX OS, LumiScan Keryx on a PC - given as an address in `input/image-address`, for example:

What is the same for every LumiScan app - how addresses are built, the handshake, execute and stream call patterns, status codes, settings and tools - is described in the [LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/index.html) manual. This manual covers only what is specific to LumiScan QR Code Reader; its own nodes are listed in the [Data Layer Reference](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/datalayer-reference.html).

```
hdvisionsystems/lumiscan-cam-driver/camera1/output/image
```

The node must publish `data`, `width`, `height` and `pixel-type`, which is what LumiScan Cam Driver provides. See [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/requirements.html).

## No modules

Unlike the LumiScan applications that search for a configured thing, this reader has **no modules**. There is one reader per installation, at one Data Layer address. On ctrlX OS one licence seat covers it.

There is nothing per-instance to configure because there is nothing to configure at all: the only input that changes between runs is which image to read.

## Seeing the results

The results are numbers on the Data Layer. To **see** them drawn on the picture they were found in, open LumiScan Cockpit: it lists this application as a single view named `qr-code` and draws a rectangle around each code, labelled with the decoded text and the score.

# Requirements – LumiScan QR Code Reader

URL: https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/requirements.html

## Licence {#licence}

How LumiScan QR Code Reader is licensed depends on where you bought it and where it runs:

| Bought from | Runs on | Licensing |
| --- | --- | --- |
| HD Vision Systems | Windows 11 or Ubuntu 24.04 | The licence is held on your LumiScan Key. It is a one-time purchase and needs no renewal.<br><br>[Licensing path: bought from HD Vision Systems](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/path-hdvs.html) |
| ctrlX Store | Windows 11 | The licence is held in ctrlX WORKS. The LumiScan Key is required in addition; it protects the software against reverse engineering.<br><br>[Licensing path: ctrlX Store, Windows](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/path-ctrlx-windows.html) |
| ctrlX Store | ctrlX OS (ctrlX CORE or IPC) | ctrlX licence `SWL-W-XCx-QRxxxCRDSxHDVSx-V1NN`, one licence per app instance. Advanced functions additionally need `SWL-W-XCx-QRxxxCRDAxHDVSx-V1NN`.<br><br>[Licensing path: ctrlX Store, ctrlX OS](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/path-ctrlx-os.html) |

Each device on which LumiScan QR Code Reader runs at the same time needs its own LumiScan Key. Keys can be exchanged between devices.

How to install CodeMeter Runtime and how to request, renew and move licences is described in [LumiScan Licensing](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/index.html).

On ctrlX OS, the licence is checked for up to ten seconds during start-up; if none becomes available, the reader shuts down and the reason is written to the system log.

If an Advanced licence is available, the application uses it automatically. If none is available, it runs with Standard functions rather than refusing to start.

## An image source on the same Data Layer

The application reads its images from another application’s Data Layer image node.

**On ctrlX OS:** that application must run on the **same ctrlX CORE or ctrlX IPC** — remote Data Layer access is not supported.

**On a PC:** that application must be connected to the same LumiScan Keryx broker as the reader (see [LumiScan Keryx on a PC](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html)).

In practice this is LumiScan Cam Driver, but any application works as long as the node named in `input/image-address` provides these four children:

| Node | Type | Description |
| --- | --- | --- |
| `data` | array of uint8 | Raw, uncompressed pixel data |
| `width` | uint64 | Image width in pixels |
| `height` | uint64 | Image height in pixels |
| `pixel-type` | string | GenICam pixel format name |

### Supported pixel formats

`Mono8`, `Mono12`, `RGB8`, `RGB12`, `BGR8`, `BGR12`, `Bayer_GR8`, `Bayer_RG8`, `Bayer_GR12`, `Bayer_RG12`.

The name is matched without regard to case, and the underscore may be left out of the Bayer names — `BayerGR8` and `bayer_gr8` are the same format. Bayer images are converted to colour before the search.

Any other pixel format is refused, and the run produces no result.

> [!NOTE]
> The image data must be **at least** `width x height x bytes-per-pixel` bytes for the declared format. A shorter buffer than the metadata promises is refused rather than read past the end.

## Storage

Reading a code stores nothing: there is no reference image and no module list, and the address in `input/image-address` lives on the Data Layer.

The image stream (experimental) keeps two things in the application’s configuration directory (see [Kept in the settings file](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#saving)): its stream mode and what it subscribes to, in `qr-code-reader.json`, saved there as they change, and what each settings hash stands for, in `settings-history/` - one small JSON file per hash, never deleted. See [Reading Codes on an Image Stream](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html).

## Timing

Reading is **synchronous**: the write to `execute` returns when the search has finished. How long that takes depends on the image size, since the whole image is searched for codes on every run.

# Reading a Code – LumiScan QR Code Reader

URL: https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-a-code.html

A run has two steps: say which image to read, then call `execute`. All paths below are relative to the application’s base path, `hdvisionsystems/lumiscan-qr-code-reader`.

## 1. Point the reader at an image

Write the address of the image node to `input/image-address`:

```
hdvisionsystems/lumiscan-cam-driver/camera1/output/image
```

This is the address of the image node **itself**, not of its `data` child — the reader appends `/data`, `/width`, `/height` and `/pixel-type` when it reads.

The address is remembered, so it only needs setting again when the image source changes.

## 2. Call execute

Write an empty value to the `execute` method.

The call is **blocking**: it returns when the search has finished. When it returns, `output/results` holds every QR code found in that image — see [The Result](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/the-result.html).

## What a run does

1. Reads the address from `input/image-address`.
2. Reads `data`, `width`, `height` and `pixel-type` from that address, and converts the pixels to an image — de-Bayering it if the format calls for that.
3. Searches the **whole** image for QR codes.
4. Writes every code it found to `output/results`.

There is no region of interest and no partial search: each run reads the entire current contents of the image node.

## When a run fails

A run fails if the image cannot be read — no address set, an address that does not resolve, a missing or short `data` buffer, or a pixel format the reader does not support. The reason is written to the application log: the ctrlX OS system log (ctrlX OS) or the console output of the app (PC).

> [!WARNING]
> A failed run leaves `output/results` **untouched**, holding the previous run’s codes. This version publishes no status node and echoes no identifier, so the result alone cannot tell you whether it is fresh. If a run’s outcome matters, check the log — or read `output/results` before and after and compare.
>
> An empty `output/results` means the image was read successfully and contained no QR code.

# The Result – LumiScan QR Code Reader

URL: https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/the-result.html

`output/results` is a flatbuffer holding one entry per QR code found, in the registered type `types/hdvisionsystems/lumiscan-qr-code-reader/code_detect_result`.

The root is an array — `CodeDetectResultArray.results` — so a run that found nothing publishes an empty array rather than an error.

## What each entry holds

| Field | Type | Description |
| --- | --- | --- |
| `center` | `Point2f` | The centre of the code in the image, in pixels |
| `text` | string | The decoded contents of the code |
| `score` | float | How confident the read is |
| `polygons` | array of `Point2f` | The corner points outlining the code in the image |

`Point2f` is a pair of floats, `x` and `y`, in image pixel coordinates. The coordinates are floats because a code’s centre and corners rarely land exactly on a pixel boundary.

## Reading it

(ctrlX OS) Over the ctrlX REST API a flatbuffer arrives as JSON, and its numbers come back **quoted** — a float is a string in the response. Parse them as numbers on your side rather than comparing them as text.

`center` and `text` are always present. `polygons` may be absent for an entry, so treat a missing outline as "no outline given" rather than as an error.

## Drawing it

To see the codes on the image rather than reading coordinates, open LumiScan Cockpit. It draws a rectangle around each code, labelled with the decoded text and the score, in a view named `qr-code`.

A code that was **located but not decoded** has no text, and Cockpit labels it with its score alone.

# Reading Codes on an Image Stream (Experimental) – LumiScan QR Code Reader

URL: https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html

> [!IMPORTANT]
> The image stream is **experimental**. Its nodes and settings may still change. Use it for evaluation, and verify it with your cameras and your Data Layer before relying on it.

`execute` reads one image per call: your program sets `input/image-address` and writes to `execute`. An image stream works the other way round. The Cam Driver publishes every image it takes on `<camera name>/control/publish/output/stream/frame`, with its size, its pixel format and its lineage (see the Cam Driver manual, *Streaming Images*). The reader subscribes to the stream of one camera, reads every QR code in each frame as it arrives, and publishes one result per frame on `control/subscribe/output/stream/result`.

Each frame is read exactly as `execute` reads an image. `execute` takes no input but the image address, and the frame takes its place. `input/parameter` is read by neither: see [Data Layer Reference](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/datalayer-reference.html).

Each result carries the lineage of its frame - which camera took it, in which run of the camera’s stream, as which frame of the run - with the reader’s own step added. See [The lineage of a result](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#lineage).

By default the reader never falls behind its camera. When frames arrive faster than the reader reads them, it takes the newest frame each time the previous read is finished. The frames in between are counted as skipped. How many frames may wait is set with the queue size, see [The queue size](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#queue-size).

How streams work in all LumiScan apps - producers and consumers, starting and stopping, the lineage - is described in [Streams](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html) of the LumiScan Keryx manual. This page describes the reader’s stream.

## The stream’s nodes {#addresses}

The reader has the stream’s nodes whether it subscribes to a stream or not. No restart is needed to start using them. All addresses below start with `hdvisionsystems/lumiscan-qr-code-reader/`. There are no modules: one stream per installation.

**Table 1. Methods**

| Address | Meaning |
| --- | --- |
| `control/subscribe/execute` | Checks the five inputs of `control/subscribe` together, saves them in the reader’s settings file, then applies them: a running stream follows on its next cycle, with no restart. Writing an input alone changes nothing. See [Changing the source](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#subscribing). |
| `control/unsubscribe/execute` | Drops the source named by `control/unsubscribe/input/address`, which ends stream mode too. The tag stays. Saved in the reader’s settings file like a subscribe. |

**Table 2. Inputs of control/subscribe**

| Address | Type | Meaning |
| --- | --- | --- |
| `control/subscribe/input/enable` | bool | Stream mode: `true` runs the stream, `false` stops it. |
| `control/subscribe/input/address` | string | The one source: a camera’s stream folder, for example `hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream`. The reader reads its `frame` node. Another address replaces the source. |
| `control/subscribe/input/tag` | string | The tag the reader puts on its results: the reader’s step in the lineage of each result carries it, so whoever reads a result downstream sees which module read it. Empty: the reader’s name, `lumiscan-qr-code-reader`. A new tag marks the next result; the source stays subscribed. |
| `control/subscribe/input/queue-size` | uint32 | How many frames may wait while a frame is read: `1` to `64`. See [The queue size](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#queue-size). |
| `control/subscribe/input/keep-latest-output` | bool | `true` to write each stream result to `output/results` as well. See [Keeping the latest output](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#keep-latest-output). |

The inputs start with what is applied at the start of the application, so a client can change one of them and execute.

What the source must hold: read `system/meta/subscription-schema`. It is a JSON Schema of the `frame` node of the source, a `stream_image` with its `lineage` and its `image`, in its JSON form. See [Data Layer Reference](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/datalayer-reference.html#system).

**Table 3. Input of control/unsubscribe**

| Address | Type | Meaning |
| --- | --- | --- |
| `control/unsubscribe/input/address` | string | The source to drop: the address `setting/stream/address` shows. A `/` at either end does not count. |

**Table 4. Settings**

| Address | Type | Meaning |
| --- | --- | --- |
| `setting/stream/enable`, `setting/stream/address`, `setting/stream/tag`, `setting/stream/queue-size`, `setting/stream/keep-latest-output` | as the inputs | What `control/subscribe/execute` or `control/unsubscribe/execute` applied last, as the settings file keeps it. Read-only. |
| `setting/settings-hash` | string | The hash of what the results are made with, as 16 hex digits. Read-only. See [The settings hash](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#settings-hash). |

**Table 5. Outputs**

| Address | Type | Meaning |
| --- | --- | --- |
| `control/subscribe/output/stream/active` | bool | `true` while the stream runs. |
| `control/subscribe/output/stream/result` | flatbuffers `stream_codes` | The codes read from each frame, and the frame’s lineage. Subscribe to it to receive each one. See [The result of a frame](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#result). |
| `control/subscribe/output/stream/last-failure` | string | Why the last frame that could not be read failed. It names the source by its address, for example `a frame of 'hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream' failed: …`. Emptied when the stream starts. |
| `control/subscribe/output/stream/statistics/…` | uint64 | Counters of the current or the last stream, see [Reading the statistics](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#statistics). |

> [!NOTE]
> `execute` writes to `output/results`, the stream to `control/subscribe/output/stream/result` - singular. The stream writes `output/results` too only with `keep-latest-output` on.

## Setting it up {#setting-up}

1. Make sure the Cam Driver’s stream runs: its `hdvisionsystems/lumiscan-cam-driver/<camera name>/control/publish/output/stream/active` is `true`.
2. Write the camera’s stream folder, for example `hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream`, to `control/subscribe/input/address`. Leave `control/subscribe/input/tag` empty to mark the results with the reader’s name, or write a tag of your own to it.
3. Subscribe to `control/subscribe/output/stream/result`.
4. Set `control/subscribe/input/enable` to `true`, then write to `control/subscribe/execute`. Wait until `control/subscribe/output/stream/active` is `true`. The results arrive from then on.
5. To stop, set `control/subscribe/input/enable` to `false` and write to `control/subscribe/execute` again. The frame being read is finished first.

On ctrlX OS, make the same writes in the Data Layer view of the ctrlX OS web interface or from your PLC program.

On a PC, the same steps with `krxclient`, the command line client of LumiScan Keryx that stands in for a PLC (see [krxclient](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/tools.html#krxclient)). Add the `--keryx-backend` and `--keryx-url` options your broker needs:

```none
krxclient write hdvisionsystems/lumiscan-qr-code-reader/control/subscribe/input/address hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream
krxclient write hdvisionsystems/lumiscan-qr-code-reader/control/subscribe/input/enable true
krxclient execute hdvisionsystems/lumiscan-qr-code-reader/control/subscribe/execute
krxclient subscribe hdvisionsystems/lumiscan-qr-code-reader/control/subscribe/output/stream/result --count 5
```

`krxclient subscribe` shows a flatbuffer by its size only. It tells you that results arrive, not what they hold.

Good to know:

- Stream mode is a **level**, not a command: the stream runs for as long as the applied `enable` is `true`.
- The stream can be started before the Cam Driver’s stream. Results arrive once frames do.
- What `control/subscribe/execute` applies is saved in the reader’s settings file. After a restart of the application the reader starts as it was: one that streamed streams again at once, without your program executing anything. See [Kept in the settings file](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#saving).

## Changing the source {#subscribing}

A reader takes one source. A PLC or another client changes it while the application runs, with or without a running stream:

1. Write the new values to the inputs of `control/subscribe` - only those you change: the others hold what is applied.
2. Write to `control/subscribe/execute`. The inputs are checked together, saved in the reader’s settings file, and only then applied: `setting/stream/` shows them at once, and a running stream follows on its next cycle. Another address replaces the source; the frames the old one had waiting are counted as skipped. A new tag, queue size or `keep-latest-output` needs no new subscription: a new tag marks the next result.
3. To drop the source, write its address to `control/unsubscribe/input/address`, then write to `control/unsubscribe/execute`. Stream mode ends with it. The inputs of `control/subscribe` are set to what it applied: stream mode off, no address. The tag stays: it marks the reader’s results, not the source.

When the settings file cannot be written, nothing changes. See [Kept in the settings file](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#saving).

The methods answer:

| ctrlX Data Layer | LumiScan Keryx | When |
| --- | --- | --- |
| `DL_OK` | `Ok` | Done. |
| `DL_INVALID_VALUE` | `Rejected` | `control/subscribe/execute`: stream mode without an address, or a queue size outside `1` to `64`. `control/unsubscribe/execute`: the address is not the source, or there is no source. |
| `DL_CREATION_FAILED` | `CreationFailed` | The settings file could not be written, for example because it is not valid JSON. Nothing changed. |

See also [Results of a method call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#method-results).

The reason for a refusal is written to the application log.

When the source cannot be subscribed to, the reader tries it again every 5 seconds while the stream runs, and logs the first failure.

## The result of a frame {#result}

`control/subscribe/output/stream/result` holds a FlatBuffers table of type `stream_codes` (file identifier `HSCD`), registered on the Data Layer as `types/hdvisionsystems/lumiscan-qr-code-reader/stream_codes`. Its compiled schema is installed as `bfbs/stream_codes.bfbs`.

| Field | Meaning |
| --- | --- |
| `lineage` | Where the result came from, see [The lineage of a result](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#lineage). |
| `result` | The codes, as a `CodeDetectResultArray`: the same table `execute` writes to `output/results` for the same picture, described in [The Result](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/the-result.html). A frame with no QR code gives an empty `results` array. |

A read of `control/subscribe/output/stream/result` returns the latest result; before the first frame, an empty one. The last result stays after the stream stops.

A frame is decoded as `execute` decodes the image node, so the same pixel formats are accepted, see [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/requirements.html). The whole frame is searched. A frame and the same picture read through `input/image-address` give the same codes.

A frame that cannot be read - for example one in a pixel format the reader does not support, or one whose pixels do not fill the size it gives - gives no result. It is counted in `statistics/failed-frames`, and `control/subscribe/output/stream/last-failure` says why.

## The lineage of a result {#lineage}

`lineage.steps` lists where the result came from, origin first:

1. The camera’s step, as the Cam Driver made it: `producer` is the camera’s address, `hdvisionsystems/lumiscan-cam-driver/<camera name>`; `run` when the camera’s stream started; `sequence` the frame’s number in that run; `external_id` the camera’s own frame number; `settings_hash` the camera’s settings; `tag` the Cam Driver’s tag for the camera, by default its module id, for example `camera1`.
2. The reader’s step: `producer` is the reader’s address, `hdvisionsystems/lumiscan-qr-code-reader`; `run` when the reader’s stream started (each start is a new run); `sequence` the result’s number in the run, from `1`; `settings_hash` the reader’s settings, see [The settings hash](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#settings-hash); `elapsed_us` the microseconds from the frame’s arrival at the reader to its result, waiting included; `time_us` when the result was made, in microseconds since the epoch; `tag` the reader’s tag, `control/subscribe/input/tag`, or `lumiscan-qr-code-reader` when it is empty.

So a result names its frame exactly: the camera by `producer`, the frame by `run` and `sequence`. To know which camera a result came from, read the `producer` of its first step. A gap in the camera step’s `sequence` between two results of the same camera is frames that were skipped, failed or lost.

A lineage holds at most 16 steps. A longer one keeps the origin and the newest steps, and `dropped` counts the steps left out.

A frame that carries no lineage gives a result with the reader’s step alone. A value on a stream’s `frame` node that is not a `stream_image` is ignored, and logged once.

## The settings hash {#settings-hash}

`setting/settings-hash`, and the `settings_hash` of the reader’s step in each result, identify what the results are made with. The node shows the hash as 16 hex digits; the step holds the same value as a number.

The reader has no setting that changes a read, so the hash covers only the code type and the application’s name and version: it changes when the application is updated. It does not cover stream mode, the source, the queue size or keep-latest-output, which choose and pace the frames.

The first time a hash appears, the reader writes the settings it stands for to `settings-history/qr-code-reader-<hash>.json` in the application’s configuration directory, so a hash found in a result can be looked up later. The application does not delete these files. A file looks like this:

```json
{
    "format": 1,
    "settings": {
        "code-type": "qr-code",
        "software.name": "lumiscan-qr-code-reader",
        "software.version": "<version>"
    },
    "settingsHash": "<16 hex digits>"
}
```

## Reading the statistics {#statistics}

The counters start from zero each time the stream starts, are updated about four times a second while it runs, and keep their last values after it stops. All addresses start with `control/subscribe/output/stream/statistics/`.

| Counter | Meaning |
| --- | --- |
| `elapsed-ms` | Milliseconds since the stream started. Divide a counter by it for a rate. |
| `received-frames` | Frames the subscription delivered. |
| `processed-frames` | Frames read, each with a result published on `control/subscribe/output/stream/result`. |
| `skipped-frames` | Frames never read: pushed out of the queue by newer ones while a frame was read (see [The queue size](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#queue-size)), or waiting when the source was replaced or dropped. |
| `failed-frames` | Frames that could not be read. `control/subscribe/output/stream/last-failure` says why the last one failed, and the log names the failures, at most one line every 5 seconds. |
| `lost-frames` | Frames dropped before they arrived, counted from gaps in the camera’s `sequence` within one run of its stream. A new source, or a new run of the camera’s stream, starts the count again. |
| `processing-us` | Microseconds all reads took, summed. Divide by `processed-frames` for the mean. |

Frames still waiting when the stream stops are dropped without being counted.

## Kept in the settings file {#saving}

Stream mode and the source are settings of the reader. They are kept in the `stream` member of the reader’s settings file, `qr-code-reader.json` in the application’s configuration directory.

`control/subscribe/execute` and `control/unsubscribe/execute` save what they apply there themselves, all five values in one write, before they apply them. When the file cannot be written, the method answers `CreationFailed` (ctrlX `DL_CREATION_FAILED`) and nothing changes. After a restart the reader subscribes to the same source and, when `stream.enable` is `true`, starts its stream at once: nobody needs to execute anything.

Saving changes only the `stream` member; the rest of the file stays as it was, comments included. The reader makes the file when there is none.

The configuration directory is:

**On ctrlX OS:** `/var/snap/rexroth-solutions/common/solutions/activeConfiguration/lumiscan-qr-code-reader`.

**On a PC (Windows):** `%APP_RESOURCE_DIR%\etc\lumiscan-qr-code-reader`; without `APP_RESOURCE_DIR`, `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-qr-code\etc\lumiscan-qr-code-reader`.

The file holds one member, `stream`. An example - on a PC, this is the example the application writes with `--generate-settings`, see [Starting from an Example](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#generate-settings):

```json
{
    // The settings of the QR Code Reader, read once, at the start: the image stream it reads codes in.
    // control/subscribe/execute and control/unsubscribe/execute save what they change here before
    // they apply it, the rest of the file left as it is, comments included.
    "$schema": "schemas/qr-code-reader.schema.json",
    "stream": {
        // Stream mode: read every frame of the source as it arrives. Off if left out.
        "enable": false,
        // The one image stream to read: its folder.
        "address": "hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream",
        // "tag" (left out here): what marks the codes it reads, in their lineage - the reader's name,
        // lumiscan-qr-code-reader, if left out.
        // How many frames may wait while a frame is read: 1 to 64, 1 if left out.
        "queueSize": 1,
        // Each stream result also on output/results, as execute writes it. Off if left out.
        "keepLatestOutput": false
    }
}
```

| Key | Required | Meaning |
| --- | --- | --- |
| `enable` | No | Stream mode: `true` starts the stream at the start of the application. Needs an `address`. `false` if left out. |
| `address` | No | The one source: a camera’s stream folder. |
| `tag` | No | What marks the reader’s results: the `tag` of the reader’s step in their lineage. The reader’s name, `lumiscan-qr-code-reader`, if left out. |
| `queueSize` | No | How many frames may wait: `1` to `64`, `1` if left out. |
| `keepLatestOutput` | No | `true` to write each stream result to `output/results` as well. `false` if left out. |
| `onEntry` | No | The steps applied to each frame as it arrives, each an object with a `kind`, as every LumiScan application’s `stream` has them. This application has none yet: leave it out, or empty (`[]`). A step starts the reader out of stream mode, with a warning in the log; saving keeps it. |

`control/subscribe/execute` and `control/unsubscribe/execute` write all five.

Good to know:

- The file is read once, at the start of the application. Changes made to the file by hand take effect at the next start.
- A value that cannot be used is ignored, and logged: an `enable` or `keepLatestOutput` that is not `true` or `false`, an `address` or `tag` that is not a string, a `queueSize` outside `1` to `64` (`1` is used). Stream mode without an `address` is ignored: the reader starts out of stream mode.
- The `subscriptions` member of earlier versions is no longer read, and the reader logs that it moved: give the source as `address`.
- A file that is not valid JSON is ignored, and logged.

## The queue size {#queue-size}

`control/subscribe/input/queue-size` sets how many frames may wait while a frame is read: `1` to `64`, `1` by default. It is saved as `stream.queueSize`, and `setting/stream/queue-size` shows the value in use. A frame that arrives when that many wait pushes out the oldest of them, which is counted in `statistics/skipped-frames`. A new queue size applies from the next frame that arrives, with no new subscription.

| Queue size | Effect |
| --- | --- |
| 1 (default) | The reader reads the newest frame. It never falls behind; when reading is slower than the camera, it skips frames. |
| More than 1 | Short bursts of frames are all read, and fewer are skipped. When reading is slower than the camera for longer, the reader falls behind: it reads frames up to that many reads old. Each waiting frame holds a whole image in memory. |

## Keeping the latest output {#keep-latest-output}

With `control/subscribe/input/keep-latest-output` `true` - applied by `control/subscribe/execute`, saved as `stream.keepLatestOutput` - the reader also writes each stream result to `output/results`, as `execute` writes it, once the result is published on `control/subscribe/output/stream/result`. A client that reads `output/results` then has the newest frame’s result without subscribing to the stream. It costs a copy of each result. Off by default.

## execute while the stream runs {#while-streaming}

`execute` and the stream do not hold each other up. Each frame is read by a detector of its own, as each call of `execute` is, and nothing is shared between the two: `execute` can be called at any time while the stream runs, and a frame never waits for it.

## Limitations {#limitations}

- `input/parameter` is read neither by `execute` nor by the stream.
- (ctrlX OS, Ubuntu) The stream has not been verified on Linux, on the ctrlX Data Layer, or with a real camera.
- (PC) The stream has been tested on Windows with LumiScan Keryx and simulated images only. It has not been verified with a real camera.
- LumiScan Cockpit does not draw the stream’s results yet.
- Changes made to the settings file by hand take effect at the next start of the application.

## Starting from an Example (PC) {#generate-settings}

On a PC, the QR Code Reader writes an example of its settings into a folder of your choice, and ends without starting. For example (Windows):

```shell
lumiscan-qr-code --generate-settings C:\work\qr-code-reader-settings
```

Without a folder (`-g` alone) it writes into the current folder. The example is the settings file `qr-code-reader.json`: stream mode off, the stream of the Cam Driver’s `camera1` as its source, the queue size it has by default and `keep-latest-output` off. Beside it, in `schemas/`, are the schema it names in `"$schema"`, `qr-code-reader.schema.json`, and `stream.schema.json`, which describes the `stream` section; an editor that understands JSON Schema can check the file against them. Copy the `schemas` folder along with it. Existing files are never overwritten: when one of them is in the folder already, nothing is written and the QR Code Reader says which.

The QR Code Reader then names the folder it reads its settings from, on Windows by default `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-qr-code\etc\lumiscan-qr-code-reader`. Edit the example, copy it there, and start the QR Code Reader.

# Data Layer Reference – LumiScan QR Code Reader

URL: https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/datalayer-reference.html

All nodes live under the application’s base path:

```
hdvisionsystems/lumiscan-qr-code-reader/
```

The paths below are given relative to it. A single read uses four nodes; the image stream (experimental) adds the nodes listed under [Image stream](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/datalayer-reference.html#stream), and [System](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/datalayer-reference.html#system) says what its source must hold.

## Data Layer {#data-layer}

LumiScan QR Code Reader offers its functions on the Data Layer under `hdvisionsystems/lumiscan-qr-code-reader`.

On ctrlX OS (ctrlX CORE or ctrlX IPC), LumiScan QR Code Reader uses the [ctrlX Data Layer](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/ctrlx-data-layer.html).

On a PC with Windows 11 or Ubuntu 24.04, LumiScan QR Code Reader uses [LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html).

The node addresses, types and call patterns are the same on both. LumiScan QR Code Reader offers:

- [execute methods](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/execute.html)
- a [stream](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html) subscription to one source (experimental)
- no module level: its nodes are directly under `hdvisionsystems/lumiscan-qr-code-reader`

How addresses are built, how to call functions, the status codes and the tools are described in [LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/index.html).

## Node tree

```
hdvisionsystems/lumiscan-qr-code-reader/
├── input/
│   ├── image-address        (string)      address of the image node to read
│   └── parameter            (flatbuffers) detection parameters
├── execute                  (method)      read every QR code in that image
├── output/
│   └── results              (flatbuffers) one entry per code found
├── control/
│   ├── subscribe/                         the image stream (experimental)
│   │   ├── execute
│   │   ├── input/{enable,address,tag,queue-size,keep-latest-output}
│   │   └── output/stream/...              the image stream's results
│   └── unsubscribe/{execute,input/address}
├── setting/{stream,settings-hash}
└── system/meta/subscription-schema    (string)      what the stream's source must hold
```

## Input

| Node | Type | Access | Description |
| --- | --- | --- | --- |
| `input/image-address` | string | read, write | Address of the Data Layer image node to read. The reader appends `/data`, `/width`, `/height` and `/pixel-type`. Empty by default, which makes a run fail until it is set. |
| `input/parameter` | flatbuffers | read, write | Detection parameters, type `types/hdvisionsystems/lumiscan-qr-code-reader/code_detect_parameters`. See the note below. |

> [!NOTE]
> `input/parameter` carries **no settings** in this version — its `DetectionParameters` table is empty. The node exists so that tuning can be added without changing the node tree. Writing to it changes nothing about how a code is read. The image stream does not read it either.

## Method

| Node | Blocking | Effect |
| --- | --- | --- |
| `execute` | Yes | Reads the image at `input/image-address` and writes every QR code found to `output/results`. Takes no argument — write an empty value. |

## Output

| Node | Type | Access | Description |
| --- | --- | --- | --- |
| `output/results` | flatbuffers | read | Every code found by the last successful run, type `types/hdvisionsystems/lumiscan-qr-code-reader/code_detect_result`. Empty array if the image held no code. See [The Result](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/the-result.html). |

## Image stream (experimental) {#stream}

The reader reads every frame of the Cam Driver stream it subscribes to, as `execute` reads an image, and publishes one result per frame. See [Reading Codes on an Image Stream](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html).

| Node | Type | Access | Description |
| --- | --- | --- | --- |
| `control/subscribe/input/enable` | bool | read, write | Stream mode: `true` runs the stream, `false` stops it. |
| `control/subscribe/input/address` | string | read, write | The one source: a camera’s stream folder, for example `hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream`. Another address replaces it. |
| `control/subscribe/input/tag` | string | read, write | The tag on the reader’s results: the reader’s step in the lineage of each stream result carries it. Empty: the reader’s name, `lumiscan-qr-code-reader`. A new tag keeps the source; the next result carries it. |
| `control/subscribe/input/queue-size` | uint32 | read, write | How many frames may wait while a frame is read, 1 to 64. |
| `control/subscribe/input/keep-latest-output` | bool | read, write | `true` to write each stream result to `output/results` as well. |
| `control/unsubscribe/input/address` | string | read, write | The source to drop, as `setting/stream/address` shows it. |
| `setting/stream/enable`, `address`, `tag`, `queue-size`, `keep-latest-output` | as the inputs | read | What `control/subscribe/execute` or `control/unsubscribe/execute` applied last, as `qr-code-reader.json` keeps it under `stream`. |
| `setting/settings-hash` | string | read | The hash of what the results are made with, as 16 hex digits. |
| `control/subscribe/output/stream/active` | bool | read | `true` while the stream runs. |
| `control/subscribe/output/stream/result` | flatbuffers | read | One result per frame read, type `types/hdvisionsystems/lumiscan-qr-code-reader/stream_codes`: the frame’s `lineage`, and `result`, the table `output/results` holds. Subscribe to it to receive each one. |
| `control/subscribe/output/stream/last-failure` | string | read | Why the last frame that could not be read failed, naming the source by its address. |
| `control/subscribe/output/stream/statistics/elapsed-ms`, `received-frames`, `processed-frames`, `skipped-frames`, `failed-frames`, `lost-frames`, `processing-us` | uint64 | read | The stream’s counters, see [Reading the statistics](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#statistics). |

| Node | Blocking | Effect |
| --- | --- | --- |
| `control/subscribe/execute` | Yes | Checks the inputs of `control/subscribe` together, saves them in `qr-code-reader.json`, then applies them. Writing an input alone changes nothing. Refused for stream mode without an address, or a queue size outside 1 to 64. |
| `control/unsubscribe/execute` | Yes | Drops the source named by `control/unsubscribe/input/address`, which ends stream mode; the tag stays. Saved in `qr-code-reader.json` like a subscribe. Refused when the address is not the source. |

The inputs of `control/subscribe` start with what is applied, and only `control/subscribe/execute` applies them. When `qr-code-reader.json` cannot be written, both methods answer `CreationFailed` (ctrlX `DL_CREATION_FAILED`) and change nothing. A refused call answers `Rejected` (ctrlX `DL_INVALID_VALUE`). See [Results of a method call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#method-results).

## System (experimental) {#system}

| Node | Type | Access | Description |
| --- | --- | --- | --- |
| `system/meta/subscription-schema` | string | read | What the node the reader subscribes to must hold: a JSON Schema (draft-04) of its JSON form. Here the `frame` node of the subscribed stream folder, a `stream_image`: an object with `lineage` and `image`. Experimental. |

## Not present in this version

Operators coming from the other LumiScan applications should know what this one does **not** publish:

- **No status node.** There is no `status-code` or `status-text`; a failed run is reported in the application log only (the ctrlX OS system log on ctrlX OS), and leaves `output/results` holding the previous run’s codes.
- **No data identifier.** There is nothing to echo back, so a result cannot be correlated with the request that produced it.
- **No result image.** The application renders nothing — no `result-image` node and no `plot` method. Use LumiScan Cockpit to see the codes drawn on the picture.
- **No modules.** One reader per installation, at the single base path above.
- **No region of interest.** Every run searches the whole image.

# FAQ – LumiScan QR Code Reader

URL: https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/faq.html

Short answers to common questions and error messages for LumiScan QR Code Reader. Each entry links to the page with the details.

> [!TIP]
> Search this page for the exact error message. Each entry has a fixed anchor (for example `#faq-failed-run`).

## Requirements and setup

### Which codes does the reader read? {#faq-what-codes}

- **Answer:** It reads QR codes, the 2D symbology with a square finder pattern in three corners. Every code found in the image is reported; there is no limit of one per run. No template, reference picture, training step or configuration is needed: you give the reader the address of an image and call `execute`.
- **More:** [Description](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/description.html)

### Which image source does the reader need? {#faq-image-source}

- **Answer:** The reader does not talk to a camera itself. It reads the image node named in `input/image-address`, published by another application on the same Data Layer - on ctrlX OS the **same ctrlX CORE or ctrlX IPC** (remote Data Layer access is not supported), on a PC the same LumiScan Keryx broker - normally LumiScan Cam Driver, for example `hdvisionsystems/lumiscan-cam-driver/camera1/output/image`. The node must provide `data` (raw, uncompressed uint8 pixel data), `width`, `height` and `pixel-type` (GenICam pixel format name). Give the address of the image node itself, not of its `data` child: the reader appends `/data`, `/width`, `/height` and `/pixel-type`.
- **More:** [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/requirements.html), [Reading a Code](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-a-code.html)

### Which pixel formats are supported? {#faq-pixel-formats}

- **Answer:** `Mono8`, `Mono12`, `RGB8`, `RGB12`, `BGR8`, `BGR12`, `Bayer_GR8`, `Bayer_RG8`, `Bayer_GR12` and `Bayer_RG12`. The name is matched without regard to case, and the underscore may be left out of the Bayer names (`BayerGR8` and `bayer_gr8` are the same format). Bayer images are converted to colour before the search. Any other pixel format is refused, and the run produces no result. The image data must be at least `width x height x bytes-per-pixel` bytes for the declared format; a shorter buffer is refused.
- **More:** [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/requirements.html)

## Reading codes

### How do I read a code? {#faq-read-code}

- **Answer:** All paths are relative to `hdvisionsystems/lumiscan-qr-code-reader`.
  - Write the address of the image node to `input/image-address`. It is remembered, so set it again only when the image source changes.
  - Write an empty value to the `execute` method. The call is blocking and returns when the search has finished.
  - Read `output/results`: it holds every QR code found in that image.
- **More:** [Reading a Code](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-a-code.html)

### What does a result entry contain? {#faq-result-fields}

- **Answer:** `output/results` is a flatbuffer (`CodeDetectResultArray.results`) with one entry per code: `center` (a `Point2f` with `x` and `y` in image pixels), `text` (the decoded contents), `score` (how confident the read is) and `polygons` (the corner points outlining the code). On ctrlX OS, over the ctrlX REST API the numbers come back quoted, as strings, so parse them as numbers. `center` and `text` are always present; `polygons` may be absent for an entry, which means no outline was given, not an error.
- **More:** [The Result](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/the-result.html)

### How do I know whether a run failed? There is no `status-code` node. {#faq-failed-run}

- **Cause:** This reader publishes no `status-code` or `status-text` node and echoes no identifier. A run fails if the image cannot be read: no address set, an address that does not resolve, a missing or short `data` buffer, or an unsupported pixel format. A failed run leaves `output/results` untouched, still holding the previous run’s codes.
- **Solution:** Check the application log, where the reason is written (the ctrlX OS system log on ctrlX OS, the console output of the app on a PC), or read `output/results` before and after the run and compare.
- **More:** [Reading a Code](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-a-code.html), [Data Layer Reference](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/datalayer-reference.html)

### Can I tune the detection, set a region of interest or create modules? {#faq-no-settings}

- **Answer:** No, not in this version. `input/parameter` carries no settings (its `DetectionParameters` table is empty), so writing to it changes nothing; the image stream does not read it either. There is no region of interest: every run searches the whole image. There are no modules: one reader per installation, at a single base path. There is also no result image; use LumiScan Cockpit to see the codes.
- **More:** [Data Layer Reference](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/datalayer-reference.html)

### How can I see the codes drawn on the image? {#faq-see-results}

- **Answer:** Open LumiScan Cockpit. It lists the reader as a view named `qr-code` and draws a rectangle around each code, labelled with the decoded text and the score. A code that was located but not decoded has no text and is labelled with its score alone. Cockpit does not draw the results of the image stream yet.
- **More:** [The Result](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/the-result.html)

### How long does a read take? {#faq-timing}

- **Answer:** Reading is synchronous: the write to `execute` returns when the search has finished. How long that takes depends on the image size, since the whole image is searched on every run.
- **More:** [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/requirements.html)

## Image stream (experimental)

### How do I read the codes in every frame of a camera stream? {#faq-stream-setup}

- **Answer:** Use the image stream (experimental). Only `control/subscribe/execute` applies its inputs: writing an input alone changes nothing. All paths are relative to `hdvisionsystems/lumiscan-qr-code-reader`.
  - Make sure the Cam Driver’s stream runs (`hdvisionsystems/lumiscan-cam-driver/<camera name>/control/publish/output/stream/active` is `true`).
  - Write the camera’s stream folder, for example `hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream`, to `control/subscribe/input/address`.
  - Subscribe to `control/subscribe/output/stream/result`.
  - Set `control/subscribe/input/enable` to `true`, then write to `control/subscribe/execute`. The results arrive once `control/subscribe/output/stream/active` is `true`.
- **More:** [Reading Codes on an Image Stream](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#setting-up), [Streams](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html)

### Where is the reader’s settings file? {#faq-settings-file}

- **Answer:** `qr-code-reader.json` is in the application’s configuration directory: on ctrlX OS `/var/snap/rexroth-solutions/common/solutions/activeConfiguration/lumiscan-qr-code-reader`; on a PC (Windows) `%APP_RESOURCE_DIR%\etc\lumiscan-qr-code-reader`, or without `APP_RESOURCE_DIR` `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-qr-code\etc\lumiscan-qr-code-reader`. On a PC, `lumiscan-qr-code --generate-settings <folder>` writes an example. The file is read once, at the start of the application.
- **More:** [Kept in the settings file](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#saving)

## Troubleshooting {#troubleshooting}

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

- [The reader shuts down during start-up](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html#faq-app-stops-after-start)
- [`output/results` is an empty array](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html#faq-empty-result)
- [`control/subscribe/execute` answers `Rejected` (ctrlX `DL_INVALID_VALUE`) or `CreationFailed` (ctrlX `DL_CREATION_FAILED`)](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html#faq-stream-refused)
- [The stream runs, but no results arrive, or `failed-frames` grows](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html#faq-stream-no-results)
- [After a restart the reader streams again by itself](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html#faq-stream-restart)

## Licensing and support

### Standard or Advanced licence - which one does the reader use? {#faq-standard-advanced}

- **Answer:** If an Advanced licence is available, the application uses it automatically. If none is available, it runs with Standard functions rather than refusing to start.
- **More:** [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/requirements.html#licence), [Licensing FAQ](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/faq.html)

### Which licence do I need? {#faq-licence}

- **Answer:** One licence seat covers the reader, since there is one reader per installation. Purchase routes:
  - Bought from HD Vision Systems: the licence is on a LumiScan Key (Windows 11 or Ubuntu 24.04). One LumiScan Key is needed per device running the software at the same time; keys can be exchanged between devices.
  - Bought in the ctrlX Store for Windows 11: ctrlX WORKS plus a LumiScan Key.
  - Bought in the ctrlX Store for ctrlX OS (ctrlX CORE or IPC): a ctrlX licence, no key.
- **More:** [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/requirements.html#licence), [Licensing FAQ](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/faq.html)

### Where can I find more answers or get support? {#faq-support}

- **Answer:** See the site-wide [LumiScan FAQ](https://docs.hdvisionsystems.com/en/faq.html), and for the Data Layer on both platforms the [Data Layer FAQ](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/faq.html). Contact HD Vision Systems customer success at [customer.success@hdvisionsystems.com](mailto:customer.success@hdvisionsystems.com) or +49 6221 6721905; for licences, [licenses@hdvisionsystems.com](mailto:licenses@hdvisionsystems.com).
- **More:** [Licensing FAQ](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/faq.html)

# Troubleshooting – LumiScan QR Code Reader

URL: https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html

This page describes problems with LumiScan QR Code Reader and how you solve them. Start with the [general checks](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html#general-checks), then find your symptom below: each problem lists its symptoms, the possible causes, a diagnostic procedure and the resolution. Problems of the Data Layer itself are described in [Data Layer troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html), licence problems in [Licensing troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/troubleshooting.html).

## General checks {#general-checks}

1. **Read the application log.** The application log is the ctrlX OS system log (ctrlX OS) or the console output of the app (PC). The reader writes the reason there when a run fails, when `control/subscribe/execute` or `control/unsubscribe/execute` is refused, when the source of the image stream cannot be subscribed to (the first failure), when frames cannot be read (at most one line every 5 seconds), and when a value in its settings file cannot be used.

2. **Check the addresses.** All nodes are directly under `hdvisionsystems/lumiscan-qr-code-reader/`; the reader has no modules. Addresses are lower case. Expected: your PLC or client uses exactly these addresses, as listed in the [Data Layer Reference](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/datalayer-reference.html).

3. **Check the image source.** The application that publishes the image node, normally LumiScan Cam Driver, must run on the **same ctrlX CORE or ctrlX IPC** (ctrlX OS) or be connected to the same LumiScan Keryx broker as the reader (PC, see [LumiScan Keryx on a PC](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html)). Expected: the node named in `input/image-address` provides `data`, `width`, `height` and `pixel-type`.

4. **Check whether a run failed.** This reader publishes no `status-code` or `status-text` node. A failed run leaves `output/results` untouched, holding the previous run’s codes. Read `output/results` before and after the run and compare, or check the log. See [How do I know whether a run failed?](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/faq.html#faq-failed-run).

5. **Check the settings file of the image stream.** The reader keeps its stream settings in `qr-code-reader.json` in the application’s configuration directory:

   | Platform | Configuration directory |
   | --- | --- |
   | ctrlX OS | `/var/snap/rexroth-solutions/common/solutions/activeConfiguration/lumiscan-qr-code-reader` |
   | PC (Windows) | `%APP_RESOURCE_DIR%\etc\lumiscan-qr-code-reader`; without `APP_RESOURCE_DIR`, `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-qr-code\etc\lumiscan-qr-code-reader` |

   The file is read once, at the start of the application: changes made to it by hand take effect at the next start. A value that cannot be used is ignored, and logged; a file that is not valid JSON is ignored, and logged. See [Kept in the settings file](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#saving).

## Problem: The reader shuts down during start-up {#faq-app-stops-after-start}

**Symptoms**

On ctrlX OS, the reader stops shortly after it starts. Its nodes under `hdvisionsystems/lumiscan-qr-code-reader` disappear from the Data Layer.

**Possible causes**

- The ctrlX licence `SWL-W-XCx-QRxxxCRDSxHDVSx-V1NN` is not available on the ctrlX OS device on which the reader runs. The licence is checked for up to ten seconds during start-up; if none becomes available, the reader shuts down.

**Diagnostic procedure**

1. Open the ctrlX OS system log - expected: the reason for the shutdown. The system log names the missing licence.
2. Check the licences in the License Manager of ctrlX OS - expected: the ctrlX licence `SWL-W-XCx-QRxxxCRDSxHDVSx-V1NN` is available on the device on which the reader runs. One licence seat covers the reader. The Advanced licence `SWL-W-XCx-QRxxxCRDAxHDVSx-V1NN` is not needed to start: without it, the reader runs with Standard functions.

**Resolution**

- **If the ctrlX licence is missing:**

  a. Buy the licence `SWL-W-XCx-QRxxxCRDSxHDVSx-V1NN` in the ctrlX Store.

  b. Activate it in the License Manager of ctrlX OS on the device on which the reader runs. Follow the Bosch Rexroth documentation for ctrlX OS.

  c. Start the reader again. Expected: it keeps running, and its nodes are on the Data Layer.

See [Licence](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/requirements.html#licence) and [My ctrlX app stops shortly after starting](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/troubleshooting.html#faq-ctrlx-app-stops).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html#support-information) to support, together with the lines of the ctrlX OS system log that name the licence. For licences, contact [licenses@hdvisionsystems.com](mailto:licenses@hdvisionsystems.com).

## Problem: `output/results` is an empty array {#faq-empty-result}

**Symptoms**

After `execute` returns, `output/results` holds an empty array: `CodeDetectResultArray.results` has no entry. In the image stream, a result on `control/subscribe/output/stream/result` has an empty `results` array.

**Possible causes**

- The image holds no QR code. An empty `output/results` is not an error: it means the image was read successfully and contained no QR code. A run that found nothing publishes an empty array rather than an error.
- The code is not a QR code. The reader reads QR codes, the 2D symbology with a square finder pattern in three corners. Data Matrix codes, Aztec codes and linear barcodes are read by its sibling applications.
- `input/image-address` names an image node that does not show the code. Each run reads the entire current contents of the image node named there.
- The last run failed, and the empty array is the result of an earlier run. A failed run leaves `output/results` untouched. A run fails if the image cannot be read: no address set, an address that does not resolve, a missing or short `data` buffer, or an unsupported pixel format.

**Diagnostic procedure**

1. Read the application log for the time of the run - expected: no failure. A failed run writes its reason there: the ctrlX OS system log (ctrlX OS) or the console output of the app (PC).
2. Read `input/image-address` - expected: the address of the image node of the camera that sees the code, for example `hdvisionsystems/lumiscan-cam-driver/camera1/output/image`.
3. Check the type of the code - expected: a QR code, with a square finder pattern in three corners.

**Resolution**

- **If the image holds no QR code:** nothing is wrong with the reader. Call `execute` again when the image node holds a picture with the code.

- **If the code is not a QR code:** use the sibling application for its symbology: LumiScan DMC Reader, LumiScan Aztec Code Reader or LumiScan Barcode Reader. They work the same way.

- **If `input/image-address` names another image node:**

  a. Write the address of the right image node to `input/image-address`. It is the address of the image node itself, not of its `data` child. The address is remembered.

  b. Write an empty value to `execute`. Expected: `output/results` holds an entry per code.

- **If the last run failed:** remove the reason the log names: set `input/image-address`, correct an address that does not resolve, or make the image source deliver complete `data` in a supported pixel format (see [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/requirements.html)). Then write an empty value to `execute` again. Expected: the log shows no failure for this run.

See [Reading a Code](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-a-code.html) and [The Result](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/the-result.html).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html#support-information) to support, together with the value of `input/image-address`, the `width`, `height` and `pixel-type` of that image node, and the symbology of the code.

## Problem: `control/subscribe/execute` answers `Rejected` (ctrlX `DL_INVALID_VALUE`) or `CreationFailed` (ctrlX `DL_CREATION_FAILED`) {#faq-stream-refused}

**Symptoms**

A write to `control/subscribe/execute` (or to `control/unsubscribe/execute`) answers `Rejected` (ctrlX `DL_INVALID_VALUE`) or `CreationFailed` (ctrlX `DL_CREATION_FAILED`) instead of `Ok` (ctrlX `DL_OK`). Nothing changed: `setting/stream/` still shows the values applied before.

**Possible causes**

- `Rejected` / `DL_INVALID_VALUE` from `control/subscribe/execute`: stream mode without an address, or a queue size outside `1` to `64`.
- `Rejected` / `DL_INVALID_VALUE` from `control/unsubscribe/execute`: the address is not the source, or there is no source.
- `CreationFailed` / `DL_CREATION_FAILED`: the settings file `qr-code-reader.json` could not be written, for example because it is not valid JSON.

**Diagnostic procedure**

1. Read the answer of the method call - expected: `Ok` or `DL_OK`. `Rejected` or `DL_INVALID_VALUE` points to an input, `CreationFailed` or `DL_CREATION_FAILED` to the settings file.
2. Read the application log - expected: the reason for the refusal. On the ctrlX Data Layer a refused call carries no reason; the reader writes it to its log.
3. After a refused `control/subscribe/execute`, read `control/subscribe/input/enable`, `control/subscribe/input/address` and `control/subscribe/input/queue-size` - expected: an address whenever `enable` is `true`, and a queue size from `1` to `64`.
4. After a refused `control/unsubscribe/execute`, compare `control/unsubscribe/input/address` with `setting/stream/address` - expected: the same address. A `/` at either end does not count.
5. After `CreationFailed` or `DL_CREATION_FAILED`, open `qr-code-reader.json` in the configuration directory (see [General checks](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html#general-checks)) - expected: a valid JSON file.

**Resolution**

- **If stream mode has no address:** write the camera’s stream folder, for example `hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream`, to `control/subscribe/input/address`, then write to `control/subscribe/execute` again. Expected: `Ok` or `DL_OK`.

- **If the queue size is outside `1` to `64`:** write a value from `1` to `64` to `control/subscribe/input/queue-size`, then write to `control/subscribe/execute` again. Expected: `Ok` or `DL_OK`.

- **If the address to drop is not the source:** write the address that `setting/stream/address` shows to `control/unsubscribe/input/address`, then write to `control/unsubscribe/execute` again. If `setting/stream/address` is empty, there is no source to drop.

- **If the settings file could not be written:**

  a. Correct `qr-code-reader.json` so that it is valid JSON. On a PC, `lumiscan-qr-code --generate-settings <folder>` writes an example to start from.

  b. Write to `control/subscribe/execute` again. Expected: `Ok` or `DL_OK`, and `setting/stream/` shows the new values.

     Changes made to the file by hand take effect at the next start of the application.

See [Changing the source](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#subscribing) and [Results of a method call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#method-results).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html#support-information) to support, together with the answer of the method call, the values of the inputs of `control/subscribe` (or `control/unsubscribe/input/address`) and `qr-code-reader.json`.

## Problem: The stream runs, but no results arrive, or `failed-frames` grows {#faq-stream-no-results}

**Symptoms**

After `control/subscribe/execute`, no result arrives on `control/subscribe/output/stream/result`, or the counter `control/subscribe/output/stream/statistics/failed-frames` grows.

**Possible causes**

- The reader’s stream does not run: the inputs of `control/subscribe` were written, but `control/subscribe/execute` was not called. Writing an input alone changes nothing.
- No frames arrive from the source: the Cam Driver’s stream does not run, or `control/subscribe/input/address` is not the camera’s stream folder. The Cam Driver’s stream is not kept across a restart of the Cam Driver.
- The source cannot be subscribed to. The reader then tries it again every 5 seconds while the stream runs.
- Frames arrive but cannot be read, for example frames in a pixel format the reader does not support, or frames whose pixels do not fill the size they give.
- Results are published, but your client does not subscribe to `control/subscribe/output/stream/result`. A read of the node returns only the latest result.

**Diagnostic procedure**

1. Read `control/subscribe/output/stream/active` - expected: `true`. If it is `false`, read `setting/stream/enable` and `setting/stream/address` - expected: `true` and the camera’s stream folder.
2. Read `hdvisionsystems/lumiscan-cam-driver/<camera name>/control/publish/output/stream/active` - expected: `true`.
3. Read `control/subscribe/output/stream/statistics/received-frames` twice, a few seconds apart - expected: the value grows. The counters are updated about four times a second while the stream runs.
4. Read `statistics/failed-frames` and `control/subscribe/output/stream/last-failure` - expected: `failed-frames` does not grow, and `last-failure` is empty. `last-failure` says why the last frame that could not be read failed; it is emptied when the stream starts.
5. Read `statistics/processed-frames` - expected: the value grows. Each processed frame has a result published on `control/subscribe/output/stream/result`.
6. Read the application log - expected: no failure to subscribe to the source, and no failed frames.

**Resolution**

- **If the reader’s stream does not run:**

  a. Write the camera’s stream folder to `control/subscribe/input/address`.

  b. Set `control/subscribe/input/enable` to `true`.

  c. Write to `control/subscribe/execute`. Expected: `Ok` or `DL_OK`, then `control/subscribe/output/stream/active` is `true`.

- **If the Cam Driver’s stream does not run:** start it, see the Cam Driver manual, *Streaming Images*. Its stream is not kept across a restart: after every start of the Cam Driver, connect the camera and call its `control/publish/execute` with `enable` = `true`. The reader’s stream can be started before the Cam Driver’s stream; results arrive once frames do.

- **If the address is not the camera’s stream folder:** write the folder, for example `hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream`, to `control/subscribe/input/address` and write to `control/subscribe/execute`. The reader reads the folder’s `frame` node. Expected: `received-frames` grows.

- **If the source cannot be subscribed to:** make sure the Cam Driver runs and publishes the stream folder named in `control/subscribe/input/address`. While the stream runs, the reader tries the source again every 5 seconds; for the same address you do not need to execute again.

- **If frames cannot be read:** read `control/subscribe/output/stream/last-failure` for the reason. Make sure the frames use a supported pixel format: `Mono8`, `Mono12`, `RGB8`, `RGB12`, `BGR8`, `BGR12`, `Bayer_GR8`, `Bayer_RG8`, `Bayer_GR12` or `Bayer_RG12` (see [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/requirements.html)). Expected: `failed-frames` stops growing.

- **If `processed-frames` grows but your client receives nothing:** subscribe to `control/subscribe/output/stream/result` to receive each result. Or set `control/subscribe/input/keep-latest-output` to `true` and write to `control/subscribe/execute`: the reader then also writes each stream result to `output/results`. `krxclient subscribe hdvisionsystems/lumiscan-qr-code-reader/control/subscribe/output/stream/result --count 5` shows that results arrive; it shows a flatbuffer by its size only.

A frame with no QR code gives a result with an empty `results` array, see [Problem: `output/results` is an empty array](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html#faq-empty-result). See also [Reading the statistics](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#statistics) and [A stream delivers nothing](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#stream-nothing).

**If the problem persists**

The image stream is experimental. On ctrlX OS, it has not been verified on Linux, on the ctrlX Data Layer, or with a real camera. On a PC, it has been tested on Windows with LumiScan Keryx and simulated images only; it has not been verified with a real camera. Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html#support-information) to support, together with the values of `control/subscribe/output/stream/active`, `control/subscribe/output/stream/last-failure`, the counters under `control/subscribe/output/stream/statistics/` and `setting/stream/`, and the value of the Cam Driver’s `control/publish/output/stream/active`.

## Problem: After a restart the reader streams again by itself {#faq-stream-restart}

**Symptoms**

After a restart of the application, `control/subscribe/output/stream/active` is `true` and results arrive on `control/subscribe/output/stream/result`, although your program has not executed anything.

**Possible causes**

- The reader starts as it was. This is intended: `control/subscribe/execute` and `control/unsubscribe/execute` save what they apply in the `stream` member of `qr-code-reader.json`. After a restart the reader subscribes to the same source and, when `stream.enable` is `true`, starts its stream at once.
- `stream.enable` was set to `true` in `qr-code-reader.json` by hand. `true` starts the stream at the start of the application.

**Diagnostic procedure**

1. Read `setting/stream/enable` and `setting/stream/address` - they show what was applied last, as the settings file keeps it. Expected, if the reader should not stream after a start: `setting/stream/enable` is `false`.
2. Open `qr-code-reader.json` in the configuration directory (see [General checks](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html#general-checks)) - expected, if the reader should not stream after a start: `stream.enable` is `false` or left out.

**Resolution**

- **If the reader should not stream after a start:** set `control/subscribe/input/enable` to `false`, then write to `control/subscribe/execute`. This stops the stream now and is saved in `qr-code-reader.json`, so the reader starts out of stream mode next time. The frame being read is finished first. Expected: `control/subscribe/output/stream/active` is `false`, and `setting/stream/enable` is `false`.
- **If the reader should not keep the source either:** write the address that `setting/stream/address` shows to `control/unsubscribe/input/address`, then write to `control/unsubscribe/execute`. Stream mode ends with it. Expected: `setting/stream/address` is empty.

See [Kept in the settings file](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/reading-codes-on-an-image-stream.html#saving).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html#support-information) to support, together with `qr-code-reader.json` and the values of `setting/stream/`.

## Information for support {#support-information}

If a problem persists, send this information to support:

- **Software version:** the version of LumiScan QR Code Reader you run. The files the image stream keeps in `settings-history/` in the configuration directory record it as `software.version`.
- **Platform:** ctrlX OS (ctrlX CORE or ctrlX IPC) and its ctrlX OS version, or a PC with Windows 11 or Ubuntu 24.04.
- **Data Layer:** the ctrlX Data Layer (ctrlX OS) or LumiScan Keryx (PC). On a PC, also the broker address the reader uses; each app names it in its log at start.
- **Log:** the application log from the time of the error: the ctrlX OS system log (ctrlX OS) or the console output of the app (PC).
- **Time:** the date and time of the error.
- **Communication status:** the answer of a refused method call (for example `Rejected` or `DL_INVALID_VALUE`), and the node values that the problem entry asks for.
- **Configuration files:** `qr-code-reader.json` and the files in `settings-history/` from the configuration directory (see [General checks](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html#general-checks)).

Contact HD Vision Systems customer success at [customer.success@hdvisionsystems.com](mailto:customer.success@hdvisionsystems.com) or +49 6221 6721905; for licences, [licenses@hdvisionsystems.com](mailto:licenses@hdvisionsystems.com).

# Release Notes: v1.0.0 – LumiScan QR Code Reader

URL: https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/release-notes/v1-0-0.html

First functioning release of LumiScan QR Code Reader.

## New

**QR code reading.** `execute` reads the image named by `input/image-address` and publishes what it found to `output/results`. Each code is reported with its decoded `text`, the `center` and the `polygons` outlining it in the image, and a `score`.

**Any image source on the same ctrlX CORE.** `input/image-address` names the image node to read, so the reader follows whatever application publishes the picture. Mono, RGB, BGR and Bayer formats are accepted at 8 and 12 bit, and Bayer images are converted to colour before the search.

**Drawn results in LumiScan Cockpit**, which lists the reader as a view named `qr-code` and draws a rectangle around each code, labelled with the decoded text and the score.

## Worth knowing

**`input/parameter` has no settings yet.** Its `DetectionParameters` table is empty; the node exists so tuning can be added later without changing the node tree.

**A failed run leaves the previous result in place.** This version publishes no status node and echoes no identifier, so `output/results` alone does not distinguish a fresh read from a stale one. The reason for a failure is written to the application log. An empty result is unambiguous: the image was read and held no QR code.

**Every run searches the whole image.** There is no region of interest, so run time scales with the image size.

## Earlier releases

**Version 0.0.1** — stub. The node tree was registered, and `execute` did no reading.

# LumiScan QR Code Reader

URL: https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/index.html

|   |   |   |
| --- | --- | --- |
| ![Two labels with QR codes](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/_images/intro/step-1.svg)<br><br>**Capture the codes.** For long payloads such as a URL or a serial number. | ![Both QR codes outlined with their decoded content](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/_images/intro/step-2.svg)<br><br>**Find and decode every code.** Any number per image, no template or training. | Example result<br><br><br><br><br><br><br>Codes<br>2<br><br><br>Text<br>SN 4711-0425-77<br><br><br>Center<br>388, 270 px<br><br>**Hand the result to your PLC.** Content and position of each code. |

LumiScan QR Code Reader finds every QR code in a camera image and reports what each one says and where it is, with no limit of one code per run. QR codes carry long payloads such as a URL or a serial number. The reader needs no template, training or configuration: give it the image address and run it, on ctrlX OS or a Windows or Ubuntu PC.

For licensing, see [Licence](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/lumiscan-qr-code-reader/requirements.html#licence). Questions? See the [FAQ](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/faq.html). A problem or an error message? See [Troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-qr-code-reader/1.0.0/troubleshooting.html).
