oqlos

OqlOS Documentation

Hardware Operator Entry Points

Before running scenarios in execute mode, use the hardware doctor:

oqlctl doctor
oqlctl detect
oqlctl doctor --json
oqlctl doctor --fix

If a global oqlctl shadows the repository CLI and lacks detect/doctor, activate .venv or call .venv/bin/oqlctl explicitly.

doctor combines host-side USB/serial/I2C discovery, Modbus RTU probing, oqlos.yaml validation, and firmware /api/v1/hardware/health + /api/v1/hardware/identify checks. It reports concrete issues such as:

Safe automatic repair is intentionally narrow: oqlctl doctor --fix updates only detected Modbus connection parameters in oqlos.yaml and writes oqlos.yaml.bak first. The current default hardware profile expects 19200 8N1 for Waveshare Modbus RTU IO 8CH; prefer stable /dev/serial/by-id/... paths over volatile /dev/ttyACM* numbering. Runtime repairs such as enabling real firmware mode, restarting containers, or mounting /dev/ttyACM*//dev/ttyUSB* remain manual and are reported as unapplied repairs when --fix is requested.

Detailed guide: Hardware Diagnostics.

oqlos

version python coverage functions

981 functions 95 classes 150 files CC̄ = 4.2

Auto-generated project documentation from source code analysis.

Author: Tom Softreck tom@sapletta.com
License: Apache-2.0(LICENSE)
Repository: https://github.com/oqlos/oqlos

Installation

From PyPI

pip install oqlos

From Source

git clone https://github.com/oqlos/oqlos
cd oqlos
pip install -e .

Optional Extras

pip install oqlos[rpi]    # rpi features
pip install oqlos[server]    # server features
pip install oqlos[dev]    # development tools
pip install oqlos[hardware-services]    # hardware-services features

Quick Start

CLI Usage

# Generate full documentation for your project
oqlos ./my-project

# Only regenerate README
oqlos ./my-project --readme-only

# Preview what would be generated (no file writes)
oqlos ./my-project --dry-run

# Check documentation health
oqlos check ./my-project

# Sync — regenerate only changed modules
oqlos sync ./my-project

Python API

from oqlos import generate_readme, generate_docs, Code2DocsConfig

# Quick: generate README
generate_readme("./my-project")

# Full: generate all documentation
config = Code2DocsConfig(project_name="mylib", verbose=True)
docs = generate_docs("./my-project", config=config)

Architecture

oqlos/
├── hw_diagnostic_20260415_133138
├── setup_hardware_and_run_oql
├── goal
├── oqlos/
├── pyqual
├── sumd
├── pyproject
    ├── testql
        ├── toon
├── TODO
├── CHANGELOG
├── Taskfile
├── openapi
├── project
├── README
    ├── cql-spec
        ├── schema
    ├── cql-examples
    ├── oql-spec
        ├── schema
    ├── HARDWARE_DIAGNOSTICS
    ├── OQL_V4_MIGRATION_MANUAL
    ├── README
    ├── plugin-config
        ├── doctor-workflow
        ├── prod
        ├── dev
    ├── Dockerfile
    ├── config
        ├── state
        ├── base
        ├── _dsl_helpers
        ├── _cql_tree_builder
        ├── _interpreter_actions
        ├── oql_parser
    ├── core/
        ├── oql_versioning
        ├── parser
        ├── _func_resolver
        ├── executor
        ├── _oql_adapter
        ├── interpreter
        ├── _cql_tokenizer
        ├── _line_parsers
        ├── safe_eval
        ├── _compare
        ├── cql_parser
        ├── _firmware_executor
        ├── _value_normalizers
        ├── _sensor_evaluator
        ├── hardware_diagnose/
        ├── plugin_cli
        ├── cql_cli/
            ├── doctor
            ├── health
            ├── __main__
            ├── modbus_probe
            ├── shell
            ├── benchmark
            ├── discovery
            ├── report
            ├── calibration
            ├── _utils
        ├── xml_import/
            ├── parser
            ├── generators
            ├── models
            ├── commands
            ├── utils
            ├── main
            ├── preflight
        ├── execution
        ├── dsl_models
        ├── scenario
        ├── peripheral
        ├── config_paths
        ├── protocol
        ├── config_schema
        ├── gateway
        ├── registry
        ├── control_proxy
    ├── hardware/
        ├── peripheral_mapping
        ├── plugin_gateway
        ├── discovery
        ├── firmware_adapter
            ├── base
            ├── registry
            ├── piadc
        ├── plugins/
            ├── modbus
            ├── lung
            ├── motor
            ├── _shared
            ├── gpio
        ├── drivers/
            ├── spi
            ├── mqtt
        ├── html_report
    ├── reporters/
        ├── json_reporter
        ├── junit
        ├── sample_data
    ├── utils/
        ├── release_version
        ├── _endpoint_helpers
        ├── file_ops
        ├── logs_query
        ├── config_factory
        ├── event_server
        ├── version_endpoint
        ├── event_store
        ├── logger
        ├── version
        ├── state
        ├── plugins
        ├── scenarios
        ├── execution
        ├── peripherals
    ├── api/
        ├── hardware
        ├── logs
        ├── editor
        ├── main
            ├── execution_ctrl
        ├── OQL-CHEATSHEET
            ├── README
        ├── schema
    ├── dsl/
    ├── oql_v4_validator
    ├── hardware-check
    ├── fix_brackets_to_v4
    ├── oql_v2_validator
    ├── migrate_to_v4
    ├── oql_v2_to_v4_migrate_db
    ├── scenarios_export
            ├── toon
            ├── toon
            ├── toon
            ├── toon
            ├── toon
    ├── manifest

API Overview

Classes

Functions

Artificial Lung Volume Commands

For OQL motor 2 reciprocating motion, the interpreter can calculate cycles from the requested volume. The default calibration is cycle volume 5 l, meaning one full back-and-forth cycle transfers 5 liters. Example: 50 liters in 30 seconds requires 10 cycles and, with stroke 1000 steps, about 667 steps/s.

VERSION: 4
GOAL:
  SET NAME 'Przetlocz 50 litrow w 30 sekund'
  SET 'motor 2' 'reciprocating motion'
  SET 'motor 2' 'stroke 1000 steps'
  SET 'motor 2' 'volume 50 l'
  SET 'motor 2' 'duration 30s'
  SET 'motor 2' 'acceleration 100%/s'
  SET 'motor 2' 'reverse on limit'
  SET 'motor 2' 'start'
  WAIT 30s
  SET 'motor 2' 'stop'

Use SET 'motor 2' 'cycle volume N l' when the calibrated volume per cycle is different from 5 liters. Plain start defaults to the left/reverse direction; use start right direction or start left direction when the initial direction must be explicit.

Project Structure

📄 CHANGELOG 📄 README 📄 TODO 📄 Taskfile 📄 Taskfile.testql 📄 docker.Dockerfile 📄 docker.docker-compose.dev 📄 docker.docker-compose.prod 📄 docs.HARDWARE_DIAGNOSTICS 📄 docs.OQL_V4_MIGRATION_MANUAL 📄 docs.README 📄 docs.cql-examples 📄 docs.cql-spec 📄 docs.oql-spec 📄 docs.oql_v2_llm_validator.schema 📄 docs.oql_v4_llm_validator.schema 📄 examples.hardware.doctor-workflow (3 functions) 📄 examples.plugin-config 📄 goal 📄 hw_diagnostic_20260415_133138 📄 openapi 📦 oqlos 📦 oqlos.api 📄 oqlos.api.editor (5 functions, 3 classes) 📄 oqlos.api.execution (16 functions) 📄 oqlos.api.hardware (31 functions) 📄 oqlos.api.logs (3 functions) 📄 oqlos.api.main (9 functions) 📄 oqlos.api.peripherals (4 functions) 📄 oqlos.api.plugins (9 functions) 📄 oqlos.api.scenarios (16 functions) 📄 oqlos.api.state (16 functions) 📄 oqlos.api.utils.execution_ctrl (3 functions) 📄 oqlos.api.version 📄 oqlos.config (1 functions, 1 classes) 📦 oqlos.core 📄 oqlos.core._compare (2 functions) 📄 oqlos.core._cql_tokenizer (27 functions) 📄 oqlos.core._cql_tree_builder (9 functions) 📄 oqlos.core._dsl_helpers (12 functions) 📄 oqlos.core._firmware_executor (9 functions, 1 classes) 📄 oqlos.core._func_resolver (4 functions) 📄 oqlos.core._interpreter_actions (48 functions) 📄 oqlos.core._line_parsers (9 functions) 📄 oqlos.core._oql_adapter (14 functions, 1 classes) 📄 oqlos.core._sensor_evaluator (6 functions, 1 classes) 📄 oqlos.core._value_normalizers (7 functions, 1 classes) 📄 oqlos.core.base (28 functions, 7 classes) 📄 oqlos.core.cql_parser (30 functions, 1 classes) 📄 oqlos.core.executor (21 functions, 1 classes) 📄 oqlos.core.interpreter (46 functions, 1 classes) 📄 oqlos.core.oql_parser (31 functions, 3 classes) 📄 oqlos.core.oql_versioning (4 functions, 1 classes) 📄 oqlos.core.parser (5 functions) 📄 oqlos.core.safe_eval (10 functions, 1 classes) 📄 oqlos.core.state (3 functions, 1 classes) 📦 oqlos.dsl 📄 oqlos.dsl.schema (6 functions, 5 classes) 📦 oqlos.hardware 📄 oqlos.hardware.config_paths (1 functions) 📄 oqlos.hardware.config_schema (4 functions, 1 classes) 📄 oqlos.hardware.control_proxy (31 functions, 3 classes) 📄 oqlos.hardware.discovery (8 functions) 📦 oqlos.hardware.drivers 📄 oqlos.hardware.drivers.gpio (7 functions, 1 classes) 📄 oqlos.hardware.drivers.mqtt (9 functions, 1 classes) 📄 oqlos.hardware.drivers.spi (7 functions, 1 classes) 📄 oqlos.hardware.firmware_adapter (24 functions, 1 classes) 📄 oqlos.hardware.gateway (25 functions, 5 classes) 📄 oqlos.hardware.peripheral_mapping (4 functions) 📄 oqlos.hardware.plugin_gateway (15 functions, 1 classes) 📦 oqlos.hardware.plugins 📄 oqlos.hardware.plugins._shared (4 functions) 📄 oqlos.hardware.plugins.base (21 functions, 9 classes) 📄 oqlos.hardware.plugins.lung (19 functions, 1 classes) 📄 oqlos.hardware.plugins.modbus (9 functions, 1 classes) 📄 oqlos.hardware.plugins.motor (18 functions, 1 classes) 📄 oqlos.hardware.plugins.piadc (12 functions, 1 classes) 📄 oqlos.hardware.plugins.registry (14 functions, 1 classes) 📄 oqlos.hardware.protocol (6 functions, 2 classes) 📄 oqlos.hardware.registry (3 functions, 1 classes) 📄 oqlos.models.dsl_models (8 classes) 📄 oqlos.models.execution (3 classes) 📄 oqlos.models.peripheral (4 classes) 📄 oqlos.models.scenario (4 classes) 📦 oqlos.reporters 📄 oqlos.reporters.html_report (5 functions) 📄 oqlos.reporters.json_reporter (2 functions) 📄 oqlos.reporters.junit (3 functions, 1 classes) 📄 oqlos.scenarios.OQL-CHEATSHEET 📄 oqlos.scenarios.examples.README 📄 oqlos.shared._endpoint_helpers (2 functions) 📄 oqlos.shared.config_factory (1 functions) 📄 oqlos.shared.event_server (11 functions, 2 classes) 📄 oqlos.shared.event_store (10 functions, 1 classes) 📄 oqlos.shared.file_ops (5 functions, 1 classes) 📄 oqlos.shared.logger (1 functions) 📄 oqlos.shared.logs_query (5 functions, 1 classes) 📄 oqlos.shared.release_version (7 functions) 📄 oqlos.shared.version_endpoint (2 functions) 📦 oqlos.tools.cql_cli (2 functions) 📄 oqlos.tools.cql_cli.commands (5 functions) 📄 oqlos.tools.cql_cli.main (16 functions, 1 classes) 📄 oqlos.tools.cql_cli.preflight (12 functions) 📄 oqlos.tools.cql_cli.utils (10 functions) 📦 oqlos.tools.hardware_diagnose (1 functions) 📄 oqlos.tools.hardware_diagnose.__main__ (8 functions) 📄 oqlos.tools.hardware_diagnose.benchmark (1 functions) 📄 oqlos.tools.hardware_diagnose.calibration (4 functions) 📄 oqlos.tools.hardware_diagnose.discovery (5 functions, 1 classes) 📄 oqlos.tools.hardware_diagnose.doctor (27 functions) 📄 oqlos.tools.hardware_diagnose.health (7 functions) 📄 oqlos.tools.hardware_diagnose.modbus_probe (16 functions) 📄 oqlos.tools.hardware_diagnose.report (2 functions) 📄 oqlos.tools.hardware_diagnose.shell (5 functions) 📄 oqlos.tools.plugin_cli (14 functions) 📦 oqlos.tools.xml_import 📄 oqlos.tools.xml_import._utils (6 functions) 📄 oqlos.tools.xml_import.generators (18 functions) 📄 oqlos.tools.xml_import.models (5 classes) 📄 oqlos.tools.xml_import.parser (6 functions) 📦 oqlos.utils 📄 oqlos.utils.sample_data (1 functions) 📄 project 📄 pyproject 📄 pyqual 📄 scenarios.manifest 📄 scripts.fix_brackets_to_v4 (2 functions) 📄 scripts.hardware-check (11 functions) 📄 scripts.migrate_to_v4 (6 functions) 📄 scripts.oql_v2_to_v4_migrate_db (17 functions, 1 classes) 📄 scripts.oql_v2_validator (9 functions, 1 classes) 📄 scripts.oql_v4_validator (10 functions, 1 classes) 📄 scripts.scenarios_export (13 functions) 📄 setup_hardware_and_run_oql (7 functions) 📄 sumd 📄 testql-contracts.testql.toon 📄 testql-scenarios.cross-project-integration.testql.toon 📄 testql-scenarios.generated-api-integration.testql.toon 📄 testql-scenarios.generated-api-smoke.testql.toon 📄 testql-scenarios.generated-from-pytests.testql.toon 📄 testql-scenarios.generated-from-scenarios.testql.toon

Requirements

Contributing

Contributors:

We welcome contributions! Open an issue or pull request to get started.

Development Setup

# Clone the repository
git clone https://github.com/oqlos/oqlos
cd oqlos

# Install in development mode
pip install -e ".[dev]"

# Run tests
pytest

Local hardware_client source fallback (dev)

oqlos.hardware.control_proxy can load hardware_client from a local source tree when the package is not available in the active virtualenv.

For multi-repo development, set:

export OQLOS_HARDWARE_CLIENT_SRC=/home/tom/github/maskservice/c2004/packages/hardware-client-py/src

This keeps local test runs and goal -a stable even when environment sync tools reinstall dependencies.

Documentation

Generated Files

Output Description Link
README.md Project overview (this file)
examples Usage examples and code samples View

Motor 2 / Artificial Lung Runtime Contract

OQL keeps artificial-lung scenarios readable:

SET 'motor 2' 'volume 50 l'
SET 'motor 2' 'duration 30s'
SET 'motor 2' 'start'

The runtime contract is modeled in oqlos.core.motor2_runtime. Store physical defaults in the MAP/UI layer and keep the algorithm in OqlOS/runtime handlers:

{
  "motor2": {
    "peripheralId": "motor-tic249",
    "strokeSteps": 1000,
    "cycleVolumeLiters": 5,
    "maxStepsPerSecond": 1000,
    "defaultSpeedStepsPerSecond": 1000,
    "accelerationPercentPerSecond": 300,
    "limitMode": "reverse_on_limit",
    "startDirection": "left"
  }
}

For volume 50 l and cycleVolumeLiters = 5, the runtime plans 10 cycles. If a duration is provided, it computes nominal steps/s from half-cycles and stroke size, then clamps it to the configured maximum. Hardware services remain responsible for final safety checks, limits, and stop/de-energize behavior.