Overview

CamCom provides a layered architecture where the core is protocol-agnostic. No protocol-specific logic (GenICam, IIDC, Aravis, etc.) exists in the core libraries or the test bench. All adapter-specific behavior is driven by YAML configuration.

Architecture

The system consists of four layers:

../_images/architecture.jpeg

CamCom architecture: GUI and web dashboard communicate with the server via HTTP/WebSocket. The server loads adapters dynamically to talk to cameras.

+----------------------------------------------------------------------+
|  camcomGui (PyQt6)      Engineering GUI, connects to server HTTP API  |
+----------------------------------------------------------------------+
        |  HTTP REST + WebSocket
        v
+----------------------------------------------------------------------+
|  Web Dashboard (HTML5)  Lightweight status page served by the server  |
+----------------------------------------------------------------------+
        |  HTTP REST
        v
+----------------------------------------------------------------------+
|  camcomServer            Generic adapter test bench                   |
|  - HTTP API: /connect /disconnect /params /status /start /stop ...   |
|  - Acquisition pipeline: capture thread -> queue -> publisher        |
|  - Recording: FITS (single, cube, MEF)                               |
|  - Telemetry, statistics, streaming (WebSocket or HTTP polling)       |
+----------------------------------------------------------------------+
        |  dlopen + AdapterBase interface
        v
+----------------------------------------------------------------------+
|  Adapter (shared library, loaded at runtime from config)             |
|  - libcamcom_genicam_arv.so  GenICam/GigE Vision via Aravis          |
|  - libcamcom_genicam_emu.so  In-process GenICam emulator             |
|  - libcamcom_sim.so          Simulated camera for testing            |
|  - (future adapters)         IIDC, custom protocols, etc.            |
+----------------------------------------------------------------------+
        |  Protocol-specific (Aravis, libdc1394, ...)
        v
+----------------------------------------------------------------------+
|  Camera hardware or emulator                                         |
+----------------------------------------------------------------------+

Key Design Principles

  1. Protocol-agnostic core. The common/ library, testbench/, and GUI have no knowledge of any specific camera protocol. Adapters are loaded at runtime via dlopen.

  2. Config is the contract. The YAML configuration file binds a specific adapter to the server. It specifies which shared library to load, which parameters the server cares about, and how to connect to the camera.

  3. Camera-native names everywhere. Across the AdapterBase boundary, all parameter names are the camera’s own names (e.g., GenICam SFNC names like ExposureTime, AcquisitionMode). The adapter does no name mapping — it is a transparent pass-through. Name translation, if desired, is the application’s responsibility.

  4. Adapters are thin wrappers. An adapter gives access to parameters and frames, nothing more. No opinions on naming, units, grouping, or constraints.

  5. Stable core, independent modules. common/ defines the contract and basic utilities. Adapters and the test bench evolve independently.

Module Structure

CamCom Modules

Module

Library / Executable

Description

common/

libcamcom_com.so

Core interfaces: AdapterBase, Parameter, FrameInfo, DataFrame, FindFile

testbench/lib/

libcamcom_testbench_lib.so

Server library: HTTP API, acquisition pipeline, recording, telemetry

testbench/app/

camcomServer

Server executable

testbench/gui/

camcomGui

PyQt6 engineering GUI

testbench/web/

(HTML/JS)

Lightweight web dashboard

simadapter/

libcamcom_sim.so

Simulated camera adapter (synthetic frames, no hardware)

genicam/lib/

libcamcom_genicam.so

GenICam core: node model, XML parser, type mapping

genicam/adapter/

libcamcom_genicam_arv.so

Production GenICam adapter (Aravis-based, optional)

genicam/emulator/

libcamcom_genicam_emu.so

In-process GenICam emulator adapter

tools/demo/

Scripts

camcomDemoStart, camcomDemoStop

CamCom supports two build systems that coexist in the repository: cmake/make (for VLT and standalone use) and waf/wtools (for ELT IFW integration). See Deployment & Examples for details.

Frame Pipeline

During acquisition, frames flow through a multi-threaded pipeline:

../_images/frame_pipeline.jpeg

Frame pipeline: the capture thread receives frames from the adapter, the publisher thread encodes and distributes them to HTTP clients and WebSocket subscribers. An optional recording branch writes FITS files.

Capture Thread              Publisher Thread              Consumers
+-----------------+         +-------------------+         +------------------+
| adapter->        |  queue  | Encode JPEG       |  HTTP   | /image endpoint  |
| ReceiveFrame()  |-------->| Update HTTP cache  |-------->| (polling)        |
+-----------------+         | Push WebSocket     |-------->| WebSocket clients|
                            +-------------------+         +------------------+
                                    |
                                    | recording queue (optional)
                                    v
                            +-------------------+
                            | FITS Recorder     |
                            | (single/cube/MEF) |
                            +-------------------+

The pipeline uses bounded queues. When a queue is full, the oldest frame is dropped and a warning is logged (throttled to once per 10 seconds).

Adapter Loading

Adapters are shared libraries loaded at runtime via dlopen. Each adapter exports a C factory function:

extern "C" {
    camcom::common::AdapterBase* CreateAdapter();
    void destroyAdapter(camcom::common::AdapterBase* adapter);
}
../_images/adapter_loading.jpeg

Adapter loading: the server reads the adapter library path from YAML config, loads it with dlopen, and calls the factory function to create an instance.

The AdapterLoader class handles the loading process:

  1. Read adapter.library from the YAML config (e.g., libcamcom_sim.so).

  2. Resolve the library path using FindFile.

  3. Call dlopen to load the shared library.

  4. Look up the factory symbol (default: CreateAdapter).

  5. Call the factory to create an AdapterBase instance.

YAML Configuration

The test bench is entirely config-driven. A YAML file specifies:

  • Which adapter library to load.

  • Camera connection parameters (URI, timeout).

  • Parameter registry with metadata (types, constraints, units).

  • Initial parameter values to apply after connection.

  • Server settings (HTTP port, image compression, streaming).

  • Recording settings (FITS format, compression, output directory).

  • Telemetry and statistics settings.

  • GUI preferences (primary parameters, poll periods).

Configs support includes — a base config (e.g., common.yaml) provides shared defaults, and camera-specific configs override as needed.

See Deployment & Examples for complete configuration reference and examples.