Configuration
Environment Variables
The application has sensible defaults for all environment variables.
Should you want to change those not via arguments but via files, you have three chances to do so:
For local development: the
.envfile should be in the project root.For normal usage, the file is in the user data directory (
user_data_dir). The location of this directory depends on the used operating system (and is also part of the log output of theicoapicommand):OS
User Data Directory
Linux
$HOME/.local/share/ICOdaqmacOS
$HOME/Library/Application Support/ICOdaqWindows
$HOME\AppData\Local\ICOdaqNote:
$HOMErefers to the directory of the currently logged in user.When no environment variable file was found, we check the bundle directory from the PyInstaller for the bundled file.
All variables prefixed with
VITE_indicate that there is a counterpart in the client side environment variables. This is to show that changes here most likely need to be propagated to the client (and Electron wrapper, for that matter).
Client/API Connection Settings
These settings determine all forms of client/API communication details.
The main REST API is versioned, does NOT use SSL at the moment and has certain origins set as secure for CORS.
VITE_API_PROTOCOL=http
VITE_API_HOSTNAME="0.0.0.0"
VITE_API_PORT=33215
VITE_API_VERSION=v1
VITE_API_ORIGINS="http://localhost,http://localhost:5173,http://localhost:33215,http://127.0.0.1:5173"
The WebSocket is for streaming data. It only requires a VITE_API_WS_PROTOCOL variable akin to VITE_API_PROTOCOL which decides between SSL or not, and how many times per second the WebSocket should send data.
VITE_API_WS_PROTOCOL=ws
WEBSOCKET_UPDATE_RATE=300
REQUIRE_INLINE_SENSOR_CONFIG controls whether a measurement request must
carry its own sensor_configuration (used for headless/orchestrated
deployments, where an upstream config service owns all configuration) or may
fall back to the locally stored sensor configuration file (the default, used
for interactive use via ICOweb). When set to 1, POST /measurement/start
and POST /measurement/execute reject a request without inline
sensor_configuration with 422, before any CAN traffic. The sensor
configuration file itself is unaffected either way - it is still loaded,
served, and restorable regardless of this setting.
REQUIRE_INLINE_SENSOR_CONFIG=0
File Storage Settings
These settings determine where the measurement and configuration files are stored locally.
VITE_APPLICATION_FOLDER=ICOdaq
VITE_APPLICATION_FOLDER expects a single folder name and locates that folder under a certain path. We use the user_data_dir() from the package platformdirs to simplify this. The system always logs which folder is used for storage.
Logging Settings
LOG_LEVEL=DEBUG
LOG_USE_JSON=0
LOG_USE_COLOR=1
LOG_PATH="C:\Users\breurather\AppData\Local\icodaq\logs"
LOG_MAX_BYTES=5242880
LOG_BACKUP_COUNT=5
LOG_NAME_WITHOUT_EXTENSION=icodaq
LOG_LEVEL_UVICORN=INFO
LOG_LEVELis one of:DEBUGINFOWARNINGERRORCRITICAL
LOG_USE_JSONformats the logs in plain JSON if set to1useful for production logs
LOG_USE_COLORformats the logs in color if set to1useful for local development in a terminal
LOG_PATHoverrides the default log location as an absolute path to a directoryYou need to have write permissions
The defaults are:
Windows:
$HOME/AppData/Local/icodaq/logsLinux/macOS:
$HOME/.local/share/icodaq/logs
LOG_NAME_WITHOUT_EXTENSIONsets the name of the logfile (without the file extension).LOG_MAX_BYETSandLOG_BACKUP_COUNTdetermine the maximum size and backup number of the logs.LOG_LEVEL_UVICORNcontrols the log level for the uvicorn web server.
MQTT
The API can publish its general state to an MQTT broker, in addition to the /state WebSocket. MQTT is only used if both MQTT_BROKER and MQTT_BASE_TOPIC are set. If only one of them is set (or a value is invalid), MQTT stays disabled and the API logs an error.
MQTT_BROKER=broker.example.com
MQTT_BASE_TOPIC=icodaq/line-3
MQTT_BROKERis the host name of the broker.MQTT_BASE_TOPICis the topic below which everything is published. It is used exactly as given (only trailing/are removed) and must not contain the wildcards+or#. Use a topic that is unique for each device if multiple devices use the same broker.MQTT_PORTsets the port of the broker (default:1883, or8883ifMQTT_TLSis enabled).MQTT_USERNAMEandMQTT_PASSWORDset the credentials.MQTT_TLSenables TLS if set to1(ortrue,yes,on). By default the CA certificates of the system are used.MQTT_TLS_CA_CERTS,MQTT_TLS_CERTFILEandMQTT_TLS_KEYFILEset the paths to a CA file and to the client certificate and key.MQTT_CLIENT_IDsets the client ID (default: chosen by the broker).MQTT_KEEPALIVEsets the keepalive in seconds (default:60).MQTT_BUFFER_SIZEsets how many messages are kept while the broker is unreachable (default:1000). Messages that do not fit into the buffer are dropped and logged as a warning.
The API publishes to the following topics:
Topic |
Content |
Retained |
|---|---|---|
|
General state (as JSON) |
yes |
|
A measurement finished (as JSON) |
no |
|
A measurement failed (as JSON) |
no |
The payload of the state topic is the same data as returned by GET /api/v1/state. The state is published again every time the API (re)connects to the broker. If the API stops, or loses the connection to the broker without disconnecting, the broker removes the retained state (an empty message is published on the topic), so an old state never claims that the API is still running.
The events about measurements are published with QoS 1. While the broker is unreachable they are kept (see MQTT_BUFFER_SIZE) and sent after the connection is restored. Their payload contains:
name: name of the measurement filesize: size of the measurement file in bytesurl: route to download the file with aGETrequest, e.g./api/v1/files/Test%20Measurement__2026-01-01_00-00-00.hdf5. It does not contain the host: clients know the address of the device and add it.error(only forFailed): thetypeandmessageof the error that stopped the measurement
size and url are null if the measurement failed before the file was created. A measurement is Finished when it ends by reaching its time or by being stopped (/api/v1/measurement/stop). Every other end (streaming timeout, unexpected error, lost client connection, cancellation) is Failed, in which case the file (if it exists) contains the data measured until then. Requests that fail before the measurement starts (e.g. /start or /execute returning an error) do not publish an event.
Both events refer to the measurement data. Post-measurement metadata can be added to the file afterwards (POST /api/v1/files/post_meta/{name}), so download the file again if you need the metadata.
Clients only read from the broker, everything a client wants to tell the API goes through the REST API. The API is the only publisher below its base topic, so give the accounts of all other clients read-only (subscribe) access to that topic in the ACL of the broker. The published data contains no secrets (CAN readiness, disk capacity, cloud status and the measurement status).
Configuration Files
The API currently works with 3 configuration files in the .yaml format:
When the API web server starts, it checks for the availability of these files in the subfolder config of the user data directory. If one of the config files does not exist, it is replaced by a copy from the default configuration files from the folder icoapi/config.
Configuration File Header
Each configuration file starts with a header (below the key info) containing information on the file and schema.
info:
schema_name: sensors_schema
schema_version: 0.0.1
config_name: General Purpose Sensor File
config_date: "2025-10-07T13:52:40+0200"
config_version: 0.0.1
The above section is exemplary for a sensor configuration file.
Sensor Configuration
ICOapi starts the measurement based on the selected measurement channels. It is up to the user to know which of the three measurement channels is connected to which sensor.
To make the channel selection easier, a layer of abstraction is present in this API and thus in the client and ICOdaq software package.
Structure
Within the sensors.yaml file, two separate areas (lists) exist:
Every element in the list below the key
sensorscontains information about a specific sensor.The data below the key
sensor_configurationsmaps a sensor channel (number) to one of the sensors (listed below the keysensors).
In addition to sensors, sensor_configurations (and the header info) a field for the default configuration, below the key default_configuration_id, exists. The file looks like this:
info: ...
sensors:
- ...
- ...
sensor_configurations:
- ...
- ...
default_configuration_id:
Sensors
Sensor information (which is also stored in the table sensors in the *.hdf5 measurement file) looks like this:
- name: Acceleration 100g
offset: -125.0
phys_max: 100.0
phys_min: -100.0
scaling_factor: 75.75757575757575 # Currently unused
sensor_id: acc100g_01 # Used by API to identify sensor
sensor_type: ADXL1001
unit: g
dimension: Acceleration
volt_max: 2.97
volt_min: 0.33
The example above defines values for the often used ±100g acceleration sensor in the x axis.
Note that the field sensor_id is what the API uses to identify the sensor for usage.
Sensor Configurations
The sensor mapping determines which sensors and channels a user can select for measurement.
The data is structured as follows:
- configuration_id: singleboard_GYRO
configuration_name: GYRO
channels:
1: { sensor_id: acc100g_01 }
6: { sensor_id: photo_01 }
8: { sensor_id: gyro_01 }
10: { sensor_id: vbat_01 }
The
configuration_id(singleboard_GYROin our example) is what the client-side.envfile can set to load as a default for tools.The
configuration_name(GYROin our example) is displayed to the client.The mapping of sensors follows the schema of
<channel>: { sensor_id: <sensor_id> }.
Default Configuration
The default_configuration_id is set to one of the configuration ids (configuration_id) of the sensor configurations (e.g. something like singleboard_GYRO in the section “Sensor Configurations”).
Metadata
To support the usage of arbitrary metadata when creating measurements, a
configuration system has been set up. This system starts as an Excel file in
which all metadata fields are defined. This file is then converted into a YAML
file (metadata.yaml).
The complete metadata logic can be found in the ICOweb repository.
The metadata is split into two parts:
the metadata entered before a measurement starts (
pre_meta)the metadata entered after the measurement has been ended (
post_meta)
This ensures that common metadata like machine tool, process or cutting parameters are set beforehand while keeping the option to require data after the fact, such as pictures or tool breakage reports.
The pre-meta is sent with the measurement instructions. The post-meta is added
to the measurement file after the measurement has stopped, using the endpoint
POST /api/v1/files/post_meta/{name} (where name is the file name including
the .hdf5 extension). The API state (running) only changes to false after
the measurement file has been closed, so post-meta can be added immediately
afterwards. The wait_for_post_meta measurement instruction is only a hint for
clients that the user should be asked for post-meta; the API does not wait for
it.
Dataspace
This file sets the dataspace connection settings if required. It simply holds all the relevant information such as:
connection:
enabled: False
username: myUser
password: strongPw123!
bucket: common
bucket_folder: default
protocol: https
domain: trident.example.com
base_path: api/v1
All relevant fields are strings without any / before or after the value. This
means that for the given example a complete endpoint would be:
https://trident.example.com/api/v1/<endpoint>
And the relevant storage would be in the folder default of the bucket
common.