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:
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
Protocol-agnostic core. The
common/library,testbench/, and GUI have no knowledge of any specific camera protocol. Adapters are loaded at runtime viadlopen.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.
Camera-native names everywhere. Across the
AdapterBaseboundary, all parameter names are the camera’s own names (e.g., GenICam SFNC names likeExposureTime,AcquisitionMode). The adapter does no name mapping — it is a transparent pass-through. Name translation, if desired, is the application’s responsibility.Adapters are thin wrappers. An adapter gives access to parameters and frames, nothing more. No opinions on naming, units, grouping, or constraints.
Stable core, independent modules.
common/defines the contract and basic utilities. Adapters and the test bench evolve independently.
Module Structure
Module |
Library / Executable |
Description |
|---|---|---|
|
|
Core interfaces: |
|
|
Server library: HTTP API, acquisition pipeline, recording, telemetry |
|
|
Server executable |
|
|
PyQt6 engineering GUI |
|
(HTML/JS) |
Lightweight web dashboard |
|
|
Simulated camera adapter (synthetic frames, no hardware) |
|
|
GenICam core: node model, XML parser, type mapping |
|
|
Production GenICam adapter (Aravis-based, optional) |
|
|
In-process GenICam emulator adapter |
|
Scripts |
|
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:
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);
}
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:
Read
adapter.libraryfrom the YAML config (e.g.,libcamcom_sim.so).Resolve the library path using
FindFile.Call
dlopento load the shared library.Look up the factory symbol (default:
CreateAdapter).Call the factory to create an
AdapterBaseinstance.
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.