Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions sample_data/docker-compose-dl-streamer-example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -458,13 +458,19 @@ services:
depends_on:
broker:
condition: service_started
web:
condition: service_healthy
environment:
- TRACKER_LOG_LEVEL=info
- TRACKER_MQTT_HOST=broker.scenescape.intel.com
- TRACKER_MQTT_PORT=1883
- TRACKER_MQTT_INSECURE=false
- TRACKER_MQTT_TLS_CA_CERT=/run/secrets/certs/scenescape-ca.pem
- TRACKER_MQTT_TLS_VERIFY_SERVER=true
- TRACKER_MANAGER_URL=https://web.scenescape.intel.com
- TRACKER_MANAGER_AUTH_PATH=/run/secrets/controller.auth
- TRACKER_MANAGER_CA_CERT_PATH=/run/secrets/certs/scenescape-ca.pem
- TRACKER_SCENES_SOURCE=api
# Override host proxy settings - Paho MQTT dont respect no_proxy var, so as a WA
# tracker code detects empty vars and unsets them (see mqtt_client.cpp clearEmptyProxyVars)
- http_proxy=
Expand All @@ -474,6 +480,7 @@ services:
secrets:
- source: root-cert
target: certs/scenescape-ca.pem
- controller.auth
restart: always
mem_limit: ${TRACKER_MEM_LIMIT:-512m}
# Scale: ~1 CPU per 100 tracked objects. Increase TRACKER_CPUS for larger deployments.
Expand Down
6 changes: 6 additions & 0 deletions tracker/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ endif()
find_package(quill REQUIRED)
find_package(CLI11 REQUIRED)
find_package(httplib REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(RapidJSON REQUIRED)
find_package(PahoMqttCpp REQUIRED)

Expand Down Expand Up @@ -70,6 +71,9 @@ set(PROJECT_SOURCE_LIST
${CMAKE_CURRENT_SOURCE_DIR}/src/cli.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/config_loader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/scene_loader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/file_scene_loader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/api_scene_loader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/manager_rest_client.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/healthcheck_server.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/healthcheck_command.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/mqtt_client.cpp
Expand Down Expand Up @@ -107,6 +111,8 @@ target_link_libraries(${PROJECT_NAME}
quill::quill
CLI11::CLI11
httplib::httplib
OpenSSL::SSL
OpenSSL::Crypto
rapidjson
PahoMqttCpp::paho-mqttpp3-static
)
Expand Down
14 changes: 7 additions & 7 deletions tracker/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ format-python:
echo "autopep8 not found. Install: pip install autopep8"; \
exit 1; \
fi
@cd test/service && autopep8 --in-place --indent-size=2 --max-line-length=120 *.py
@cd test/service && autopep8 --in-place --indent-size=2 --max-line-length=120 *.py mocks/*.py
@echo "βœ“ Python files formatted"

install-hooks:
Expand Down Expand Up @@ -111,7 +111,7 @@ lint-python:
echo "autopep8 not found. Install: pip install autopep8"; \
exit 1; \
fi
@cd test/service && autopep8 --diff --exit-code --indent-size=2 --max-line-length=120 *.py && echo "βœ“ Python lint passed"
@cd test/service && autopep8 --diff --exit-code --indent-size=2 --max-line-length=120 *.py mocks/*.py && echo "βœ“ Python lint passed"

lint-trivy:
@echo "Running Trivy security scan..."
Expand Down Expand Up @@ -178,7 +178,7 @@ TRACKER_CONFIG_PATH ?= $(CURDIR)/config/tracker.json

# MQTT broker connection (auto-detect from test broker, fallback to 1883)
export TRACKER_MQTT_HOST ?= localhost
export TRACKER_MQTT_PORT ?= $(shell cd test/service && docker compose port broker 1883 2>/dev/null | cut -d: -f2 || echo 1883)
export TRACKER_MQTT_PORT ?= $(shell cd test/service && docker compose -f compose/docker-compose.yaml port broker 1883 2>/dev/null | cut -d: -f2 || echo 1883)

# Export empty proxy vars - Paho MQTT library fails with proxy env vars,
# tracker code detects empty vars and unsets them (see mqtt_client.cpp)
Expand Down Expand Up @@ -377,12 +377,12 @@ generate-certs:
fi

broker-start: generate-certs
@cd test/service && docker compose up -d broker
@cd test/service && docker compose -f compose/docker-compose.yaml up -d broker
@sleep 1
@echo "βœ“ Broker running on port $$(cd test/service && docker compose port broker 1883 | cut -d: -f2)"
@echo "βœ“ Broker running on port $$(cd test/service && docker compose -f compose/docker-compose.yaml port broker 1883 | cut -d: -f2)"

broker-stop:
@cd test/service && docker compose down
@cd test/service && docker compose -f compose/docker-compose.yaml down
@echo "βœ“ Broker stopped"

#####################################################################
Expand All @@ -408,7 +408,7 @@ mqtt-publish:

# Override common.mk clean to also remove local build directories
clean:
-@cd test/service && docker compose down 2>/dev/null || true
-@cd test/service && docker compose -f compose/docker-compose.yaml down 2>/dev/null || true
rm -rf build* test/service/.venv test/service/.certs test/service/.env .pytest_cache
-docker rmi $(IMAGE):$(VERSION) $(IMAGE):latest 2>/dev/null || true
-rm -f $(BUILD_DIR)/$(IMAGE)-*deps.txt $(LOG_FILE) 2>/dev/null || true
2 changes: 1 addition & 1 deletion tracker/conanfile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ CMakeDeps
CMakeToolchain

[options]
cpp-httplib/*:with_openssl=False
cpp-httplib/*:with_openssl=True
opencv/*:shared=True
opencv/*:tracking=True
opencv/*:video=True
Expand Down
7 changes: 5 additions & 2 deletions tracker/config/tracker.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
"healthcheck": {
"port": 8080
}
},
"manager": {
"url": "https://web.scenescape.intel.com",
"auth_path": "/run/secrets/controller.auth"
}
},
"observability": {
Expand All @@ -17,7 +21,6 @@
}
},
"scenes": {
"source": "file",
"file_path": "scenes.json"
"source": "api"
}
}
16 changes: 16 additions & 0 deletions tracker/inc/config_loader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,22 @@ struct TrackerConfig {
bool schema_validation = true;
};

/**
* @brief Manager REST API connection settings.
*/
struct ManagerConfig {
std::string url; ///< Manager API base URL
std::string auth_path; ///< Path to JSON auth file {user, password}
std::optional<std::string> ca_cert_path; ///< CA cert for HTTPS (falls back to MQTT TLS CA)
};

/**
* @brief External service connections.
*/
struct InfrastructureConfig {
MqttConfig mqtt;
TrackerConfig tracker;
std::optional<ManagerConfig> manager; ///< Required when scenes.source='api'
};

/**
Expand Down Expand Up @@ -98,6 +108,12 @@ constexpr char INFRASTRUCTURE_MQTT_TLS_CLIENT_KEY_PATH[] =
"/infrastructure/mqtt/tls/client_key_path";
constexpr char INFRASTRUCTURE_MQTT_TLS_VERIFY_SERVER[] = "/infrastructure/mqtt/tls/verify_server";

// Manager
constexpr char INFRASTRUCTURE_MANAGER[] = "/infrastructure/manager";
constexpr char INFRASTRUCTURE_MANAGER_URL[] = "/infrastructure/manager/url";
constexpr char INFRASTRUCTURE_MANAGER_AUTH_PATH[] = "/infrastructure/manager/auth_path";
constexpr char INFRASTRUCTURE_MANAGER_CA_CERT_PATH[] = "/infrastructure/manager/ca_cert_path";

// Scenes
constexpr char SCENES_SOURCE[] = "/scenes/source";
constexpr char SCENES_FILE_PATH[] = "/scenes/file_path";
Expand Down
19 changes: 19 additions & 0 deletions tracker/inc/env_vars.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,23 @@ constexpr const char* MQTT_TLS_VERIFY_SERVER = "TRACKER_MQTT_TLS_VERIFY_SERVER";
/// (true/false)
constexpr const char* MQTT_SCHEMA_VALIDATION = "TRACKER_MQTT_SCHEMA_VALIDATION";

// Manager API overrides

/// Environment variable for overriding Manager API base URL
constexpr const char* MANAGER_URL = "TRACKER_MANAGER_URL";

/// Environment variable for overriding Manager API auth file path
constexpr const char* MANAGER_AUTH_PATH = "TRACKER_MANAGER_AUTH_PATH";

/// Environment variable for overriding Manager API CA certificate path
constexpr const char* MANAGER_CA_CERT_PATH = "TRACKER_MANAGER_CA_CERT_PATH";

// Scenes overrides

/// Environment variable for overriding scene source ("file"|"api")
constexpr const char* SCENES_SOURCE = "TRACKER_SCENES_SOURCE";

/// Environment variable for overriding scene file path
constexpr const char* SCENES_FILE_PATH = "TRACKER_SCENES_FILE_PATH";

} // namespace tracker::env
56 changes: 56 additions & 0 deletions tracker/inc/manager_rest_client.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// SPDX-FileCopyrightText: 2026 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include <optional>
#include <string>

namespace tracker {

/**
* @brief HTTP client for Manager REST API.
*
* Handles authentication and scene fetching from the SceneScape Manager.
* Supports HTTPS with CA certificate verification.
*/
class ManagerRestClient {
public:
/**
* @brief Construct a Manager REST API client.
*
* @param url Manager API base URL (e.g., "https://web.scenescape.intel.com")
* @param ca_cert_path Optional CA certificate path for HTTPS verification
*/
ManagerRestClient(std::string url, std::optional<std::string> ca_cert_path = std::nullopt);

/**
* @brief Authenticate with the Manager API.
*
* Sends POST to {url}/auth with form data (username, password).
* Stores the returned token for subsequent requests.
*
* @param username API username
* @param password API password
* @throws std::runtime_error on connection failure, HTTP error, or auth rejection
*/
void authenticate(const std::string& username, const std::string& password);

/**
* @brief Fetch all scenes from the Manager API.
*
* Sends GET to {url}/api/v1/scenes with Authorization header.
* Must call authenticate() first.
*
* @return Raw JSON response body string
* @throws std::runtime_error if not authenticated, connection fails, or HTTP error
*/
std::string fetchScenes();

private:
std::string url_;
std::optional<std::string> ca_cert_path_;
std::string token_;
};

} // namespace tracker
20 changes: 16 additions & 4 deletions tracker/inc/scene_loader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ struct Scene {
*/
enum class SceneSource {
File, ///< Load scenes from external JSON file (scenes.file_path)
Api ///< Fetch scenes from Manager REST API (not yet implemented)
Api ///< Fetch scenes from Manager REST API
};

/**
* @brief Scene configuration source settings.
*/
struct ScenesConfig {
SceneSource source = SceneSource::File; ///< Scene source type
std::optional<std::string> file_path; ///< Path to scene file (when source=File)
SceneSource source = SceneSource::Api; ///< Scene source type (default: API)
std::optional<std::string> file_path; ///< Path to scene file (when source=File)
};

/**
Expand All @@ -101,6 +101,9 @@ class ISceneLoader {
virtual std::vector<Scene> load() = 0;
};

// Forward declaration (defined in config_loader.hpp)
struct ManagerConfig;

/**
* @brief Create a scene loader based on configuration.
*
Expand All @@ -109,11 +112,20 @@ class ISceneLoader {
*
* @param config Scene source configuration
* @param config_dir Directory containing config file (for resolving relative paths)
* @param manager_config Pointer to Manager API config (required when source=Api, nullptr otherwise)
* @param schema_dir Directory containing schema files (for API response validation)
* @return Unique pointer to the scene loader implementation
* @throws std::runtime_error if configuration is invalid
*/
std::unique_ptr<ISceneLoader> create_scene_loader(const ScenesConfig& config,
const std::filesystem::path& config_dir);
const std::filesystem::path& config_dir,
const ManagerConfig* manager_config = nullptr,
const std::filesystem::path& schema_dir = {});

// Internal factory functions used by create_scene_loader (defined in separate TUs)
std::unique_ptr<ISceneLoader> create_file_scene_loader(const std::filesystem::path& file_path);
std::unique_ptr<ISceneLoader> create_api_scene_loader(const ManagerConfig& manager_config,
const std::filesystem::path& schema_dir);

/// JSON Pointer paths (RFC6901) for scene/camera fields
namespace scene_json {
Expand Down
Loading
Loading