# Configuration
An open.CONNECT instance is configured on three levels:
1. the **`.env` file** — what the instance does and where it gets its configuration;
2. **devices** — one entry per connection (PLC, server, folder, …);
3. **items** — one entry per value to read from a device.
Devices and items come either from a JSON **config file** (`OC_OFFLINE = true`) or
from a **Parse server** (`OC_OFFLINE = false`).
## Environment variables
| Variable | Meaning |
|---|---|
| `OC_CAP_FLAGS` | Comma-separated capabilities: `plc`, `api`, `manage`, `mqttwrite` — see the [Übersicht](Developer/open.CONNECT/Übersicht.md#capabilities). |
| `OC_OFFLINE` | `true` → load devices/items from the file `OC_OFFLINE_FILE`; `false` → load from Parse. |
| `OC_OFFLINE_FILE` | Path of the JSON config file, e.g. `configs/config.json`. |
| `OC_REFRESH_INTERVAL` | How often (ms) the configuration is re-checked for changes. Changed devices are restarted automatically. |
| `OC_PARSE_HOST` / `OC_PARSE_APPID` / `OC_PARSE_USER` / `OC_PARSE_PASSWORD` | Parse server connection (only with `OC_OFFLINE = false`). |
| `OC_WEBAPI_PORT` | Port of the web API / management UI (default `80`). |
| `OC_WEBAPI_SECRET` | HMAC secret for the API tokens and login password of the management UI. |
| `OC_THREAD_POOLSIZE` | Size of the reader thread pool (default `4`). |
| `OC_MQTT_WRITE_HOST` / `OC_MQTT_WRITE_CLIENTID` / `OC_MQTT_WRITE_USERNAME` / `OC_MQTT_WRITE_PASSWORD` | Broker connection of the [MQTT write API](write-api.md#writing-via-mqtt) (capability `mqttwrite`). |
| `OC_UPTIME_KUMA_HEARTBEAT` | Optional Uptime-Kuma heartbeat URL, pinged by the configuration runnable. |
| `MAIL_*` | Optional SMTP settings for mail notifications (`MAIL_ENABLE`, `MAIL_HOST`, `MAIL_PORT`, `MAIL_USERNAME`, `MAIL_PASSWORD`, `MAIL_FROM_ADDRESS`, `MAIL_TO_ADDRESS`, `MAIL_STARTTLS`, `MAIL_SMTP_SSL_ENABLE`, `MAIL_SSL_TRUST`). |
## Config file structure
```json
{
"devices": [ { "…": "one entry per connection" } ],
"items": [ { "…": "one entry per value" } ]
}
```
## Device options
These fields work the same for every adapter:
| Option | Type | Default | Meaning |
|---|---|---|---|
| `connectionString` | string | — | Selects the adapter (prefix = adapter id) and carries host/port/path, e.g. `modbus.tcp://10.0.0.5:502`. |
| `objectId` | string | — | Unique device id. Items reference it, and the write API addresses the device by it. |
| `enabled` | boolean | — | If `false`, the device is skipped and no reader thread is started. |
| `interval` | long (ms) | — | Poll period, scheduled as a **fixed delay** between consecutive runs. |
| `watch` | long (ms) | `0` | Watchdog. If `> 0` and there was no successful run within `watch` ms, the process exits and relies on the container/service manager to restart it. |
| `name` | string | — | Human-readable device name; used as the source name of the produced data items. |
| `options` | object | `{}` | **Protocol-specific** settings — documented on each [adapter page](/docs/openconnect/adapters). |
| `extraOptions` | object | `{}` | MQTT output settings, see below. |
**`extraOptions` — MQTT output per device:**
| Key | Meaning |
|---|---|
| `host` | MQTT broker (`host[:port]`, connected as `tcp://…`). Empty → this device publishes nothing. |
| `clientId` | Base client id (suffixed with the device `objectId` and a timestamp). |
| `username` / `password` | Optional broker credentials. |
| `prefix` / `suffix` | Prepended/appended to every published topic. |
## Item options
| Option | Type | Meaning |
|---|---|---|
| `objectId` | string | Unique item id. |
| `DeviceID.objectId` | string | The device this item belongs to. |
| `address` | string | **Protocol-specific** address of the value — documented on each [adapter page](/docs/openconnect/adapters). |
| `label` | string | Display name of the value dimension. |
| `unit` | string | Unit of the value dimension. |
| `type` | string | Value type: `Number`, `Boolean`, `String`, `Object`. |
| `source.tag` | string | Source/tag of the produced data item (part of the MQTT topic). |
| `enabled` | boolean | Only enabled items are read. |
| `onChange` | boolean | If `true`, publish only when the value changed. Without a threshold, unchanged values are suppressed within a 60 s window. |
**`extraOptions` — item pipeline:**
| Key | Shape | Behaviour |
|---|---|---|
| `scale` | `{ "factor": 1.0, "offset": 0.0 }` | Linear transform on each numeric dimension: `new = value * factor + offset`. |
| `changeThreshold` | `{ "type": "absolute", "threshold": 0.5 }` | Refines `onChange`. `absolute` → resend when the difference exceeds `threshold`; any other type → relative: resend when the old value is `0` or the relative change exceeds `threshold`. |
| `useManualId` | string | Overrides the produced item id. |
| `overwrites` | object | Post-read overrides: `name`, `source`, `id`, `meta`, and per-dimension `valueTypes[].name` / `valueTypes[].unit`. |
| `valueTypes` | array | Declares multiple dimensions for items whose address yields more than one value: `[{ "name": "…", "unit": "…", "type": "Number" }, …]`. |
Example item using the pipeline options:
```json
{
"objectId": "temp1",
"DeviceID": { "objectId": "plc1" },
"address": "HR::16int::100::1",
"label": "Temperature",
"type": "Number",
"unit": "°C",
"source": { "tag": "hall1/oven" },
"enabled": true,
"onChange": true,
"extraOptions": {
"scale": { "factor": 0.1, "offset": 0 },
"changeThreshold": { "type": "absolute", "threshold": 0.5 }
}
}
```
## Connection and retry behaviour
- **Connect backoff:** exponential — `2^min(8, retries)` seconds between connection
attempts, reset on success.
- **MQTT reconnect:** throttled to at most once every 30 s; reconnects automatically
on connection loss.
- **Subscriptions:** adapters that support subscriptions register the items once
(first successful run) and receive pushed values; all others are polled every
`interval` ms.
- **Config refresh:** the configuration is re-read every `OC_REFRESH_INTERVAL` ms;
changed devices are restarted with their new settings.
## Parse-based configuration
With `OC_OFFLINE = false`, devices and items are loaded from the Parse classes
`OWPlcDevice` and the item class, using the same fields as the file-based
configuration. An item object then carries the usual Parse metadata in addition —
for reference, this is what an item looks like when it comes from Parse:
```json
{
"objectId": "XX",
"address": "XX::XX::XX",
"onChange": false,
"DeviceID": { "__type": "Pointer", "className": "OWPlcDevice", "objectId": "XXX" },
"label": "Some name",
"type": "Number",
"unit": "#",
"enabled": true,
"source": {
"__type": "Object",
"className": "OD3_Source",
"objectId": "XX",
"name": "XX",
"tag": "some tag"
},
"extraOptions": { "note": "some note", "charset": "UTF-8", "persist": true }
}
```
## Sync files (API mapping)
For instances that map values between HTTP APIs (capability `api` with sync
services), a sync file in the `sync/` folder describes the field mapping. The mapper
uses Apache Velocity templates to extract and replace fields:
```json
{
"from-service": {
"to-service": {
"request-type": {
"targetField": { "value": "$source.id", "type": "string" }
}
}
}
}
```