Skip to content

Commit e8d2619

Browse files
Józef DanieckitdorauintcCopilotscenescapecicdltalarcz
authored
Tracker service v0.2.0: mqtt support (#923)
Co-authored-by: Tomasz Dorau <tomasz.dorau@intel.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: scenescapecicd <sys_scenescape_ci@intel.com> Co-authored-by: Lukasz Talarczyk <lukasz.talarczyk@intel.com> Co-authored-by: Dmytro Yermolenko <dmytro.yermolenko@intel.com>
1 parent 674535b commit e8d2619

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3817
-219
lines changed

.github/resources/.prettierignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,10 @@
55
**/kubernetes/**/*.yaml
66
**/.reuse/templates/template.jinja2
77
.venv
8+
9+
# Build directories (CMake/Conan generated)
10+
**/build/
11+
**/build-*/
12+
**/CMakeUserPresets.json
13+
**/CMakePresets.json
14+
**/CMakeFiles/

sample_data/docker-compose-dl-streamer-example.yml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,25 @@ services:
441441
aliases:
442442
- tracker.scenescape.intel.com
443443
user: "10001:10001"
444+
depends_on:
445+
broker:
446+
condition: service_started
444447
environment:
445-
- LOG_LEVEL=${TRACKER_LOG_LEVEL:-info}
448+
- TRACKER_LOG_LEVEL=info
449+
- TRACKER_MQTT_HOST=broker.scenescape.intel.com
450+
- TRACKER_MQTT_PORT=1883
451+
- TRACKER_MQTT_INSECURE=false
452+
- TRACKER_MQTT_TLS_CA_CERT=/run/secrets/certs/scenescape-ca.pem
453+
- TRACKER_MQTT_TLS_VERIFY_SERVER=true
454+
# Override host proxy settings - Paho MQTT dont respect no_proxy var, so as a WA
455+
# tracker code detects empty vars and unsets them (see mqtt_client.cpp clearEmptyProxyVars)
456+
- http_proxy=
457+
- https_proxy=
458+
- HTTP_PROXY=
459+
- HTTPS_PROXY=
460+
secrets:
461+
- source: root-cert
462+
target: certs/scenescape-ca.pem
446463
restart: always
447464
mem_limit: ${TRACKER_MEM_LIMIT:-512m}
448465
# Scale: ~1 CPU per 100 tracked objects. Increase TRACKER_CPUS for larger deployments.

tracker/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ endif()
4444
# Find Conan-installed packages
4545
find_package(quill REQUIRED)
4646
find_package(CLI11 REQUIRED)
47-
find_package(simdjson REQUIRED)
4847
find_package(httplib REQUIRED)
4948
find_package(RapidJSON REQUIRED)
49+
find_package(PahoMqttCpp REQUIRED)
5050

5151
#####################################################################
5252
# RobotVision integration
@@ -75,6 +75,9 @@ set(PROJECT_SOURCE_LIST
7575
${CMAKE_CURRENT_SOURCE_DIR}/src/config_loader.cpp
7676
${CMAKE_CURRENT_SOURCE_DIR}/src/healthcheck_server.cpp
7777
${CMAKE_CURRENT_SOURCE_DIR}/src/healthcheck_command.cpp
78+
${CMAKE_CURRENT_SOURCE_DIR}/src/mqtt_client.cpp
79+
${CMAKE_CURRENT_SOURCE_DIR}/src/message_handler.cpp
80+
${CMAKE_CURRENT_SOURCE_DIR}/src/proxy_utils.cpp
7881
)
7982

8083
add_executable(${PROJECT_NAME}
@@ -105,9 +108,9 @@ target_link_libraries(${PROJECT_NAME}
105108
RobotVision
106109
quill::quill
107110
CLI11::CLI11
108-
simdjson::simdjson
109111
httplib::httplib
110112
rapidjson
113+
PahoMqttCpp::paho-mqttpp3-static
111114
)
112115

113116
#####################################################################

tracker/Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,11 @@ ARG GIT_COMMIT=unknown
5858
RUN GIT_COMMIT=${GIT_COMMIT} cmake --build build -j
5959

6060
# Collect all runtime library dependencies for the tracker binary
61-
RUN mkdir -p /scenescape/runtime-libs
6261
WORKDIR /scenescape/runtime-libs
6362
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
64-
RUN . /scenescape/build/conanrun.sh && ldd /scenescape/build/tracker \
63+
# hadolint ignore=SC1091
64+
RUN mkdir -p /scenescape/runtime-libs \
65+
&& . /scenescape/build/conanrun.sh && ldd /scenescape/build/tracker \
6566
| awk '{print $3}' \
6667
| grep '^/' \
6768
| xargs -I '{}' cp -v '{}' .

tracker/Makefile

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ SRC_FILES := $(wildcard src/*.cpp) $(wildcard inc/*.hpp) $(wildcard test/unit/*.
2828
build build-debug build-relwithdebinfo run run-debug profile flamegraph \
2929
test-unit test-unit-coverage test-service clean install-tools install-deps \
3030
run-image run-image-debug format-cpp lint-cpp format-python lint-python install-hooks \
31-
lint-dockerfile lint-trivy lint-all coverage-html coverage-xml coverage-report
31+
lint-dockerfile lint-trivy lint-all coverage-html coverage-xml coverage-report \
32+
mqtt-subscribe mqtt-publish broker-start broker-stop generate-certs
3233

3334
all: build
3435

@@ -81,6 +82,7 @@ install-hooks:
8182
@echo "Installing git pre-commit hook..."
8283
@mkdir -p ../.git/hooks
8384
@echo '#!/bin/bash' > ../.git/hooks/pre-commit
85+
@echo 'set -e' >> ../.git/hooks/pre-commit
8486
@echo 'make prettier-check' >> ../.git/hooks/pre-commit
8587
@echo 'cd tracker && make lint-cpp && make lint-python && make lint-dockerfile' >> ../.git/hooks/pre-commit
8688
@chmod +x ../.git/hooks/pre-commit
@@ -173,11 +175,20 @@ build-relwithdebinfo: dependencies-relwithdebinfo
173175
# Schema and config paths for local development
174176
TRACKER_SCHEMA_PATH ?= $(CURDIR)/schema/config.schema.json
175177
TRACKER_CONFIG_PATH ?= $(CURDIR)/config/tracker.json
178+
179+
# MQTT broker connection (auto-detect from test broker, fallback to 1883)
180+
export TRACKER_MQTT_HOST ?= localhost
181+
export TRACKER_MQTT_PORT ?= $(shell cd test/service && docker compose port broker 1883 2>/dev/null | cut -d: -f2 || echo 1883)
182+
183+
# Export empty proxy vars - Paho MQTT library fails with proxy env vars,
184+
# tracker code detects empty vars and unsets them (see mqtt_client.cpp)
176185
run: build
177-
. build/conanrun.sh && ./build/$(NAME) --config $(TRACKER_CONFIG_PATH) --schema $(TRACKER_SCHEMA_PATH)
186+
export http_proxy= https_proxy= HTTP_PROXY= HTTPS_PROXY= && \
187+
. build/conanrun.sh && ./build/$(NAME) --config $(TRACKER_CONFIG_PATH) --schema $(TRACKER_SCHEMA_PATH)
178188

179189
run-debug: build-debug
180-
. build-debug/conanrun.sh && ./build-debug/$(NAME) --config $(TRACKER_CONFIG_PATH) --schema $(TRACKER_SCHEMA_PATH)
190+
export http_proxy= https_proxy= HTTP_PROXY= HTTPS_PROXY= && \
191+
. build-debug/conanrun.sh && ./build-debug/$(NAME) --config $(TRACKER_CONFIG_PATH) --schema $(TRACKER_SCHEMA_PATH)
181192

182193
# Profile with perf using optimized build with debug symbols.
183194
# Requires perf permissions. If you see "Error: Failure to open event", run:
@@ -238,6 +249,7 @@ coverage-html:
238249
'*/external/*' \
239250
'*/third_party/*' \
240251
'*/src/main.cpp' \
252+
'*/src/mqtt_client.cpp' \
241253
--output-file build-debug/coverage/coverage-filtered.info \
242254
--rc branch_coverage=1 \
243255
--ignore-errors unused \
@@ -267,6 +279,7 @@ coverage-xml:
267279
--exclude '.*external.*' \
268280
--exclude '.*third_party.*' \
269281
--exclude '.*main\.cpp' \
282+
--exclude '.*mqtt_client\.cpp' \
270283
--xml-pretty \
271284
--xml build-debug/coverage/coverage.xml \
272285
--exclude-unreachable-branches \
@@ -291,6 +304,7 @@ coverage-report:
291304
--exclude '.*external.*' \
292305
--exclude '.*third_party.*' \
293306
--exclude '.*main\.cpp' \
307+
--exclude '.*mqtt_client\.cpp' \
294308
--exclude-unreachable-branches \
295309
--print-summary \
296310
--fail-under-line 90.0 \
@@ -305,7 +319,8 @@ test-service: build-image
305319
@test/service/.venv/bin/pip install -q --upgrade pip
306320
@test/service/.venv/bin/pip install -q -r test/service/requirements.txt
307321
@echo "Running service tests..."
308-
cd test/service && .venv/bin/pytest -v --tb=short
322+
unset TRACKER_MQTT_PORT TRACKER_MQTT_HOST TRACKER_MQTT_INSECURE && \
323+
cd test/service && .venv/bin/pytest -v --tb=short
309324

310325
#####################################################################
311326
# Docker build targets
@@ -324,8 +339,11 @@ build-image-debug:
324339
build-image-relwithdebinfo:
325340
$(MAKE) build-image TARGET=runtime BUILD_TYPE=RelWithDebInfo IMAGE=scenescape-tracker-relwithdebinfo
326341

342+
# Use host network to reach broker on localhost; empty proxy vars for Paho workaround
327343
run-image: build-image
328-
docker run --rm -it $(IMAGE):$(VERSION)
344+
docker run --rm -it --network=host \
345+
-e http_proxy= -e https_proxy= -e HTTP_PROXY= -e HTTPS_PROXY= \
346+
$(IMAGE):$(VERSION)
329347

330348
run-image-debug: build-image-debug
331349
-docker stop tracker-debug 2>/dev/null || true
@@ -339,12 +357,58 @@ stop-image-debug:
339357
-docker stop tracker-debug 2>/dev/null || true
340358
-docker rm tracker-debug 2>/dev/null || true
341359

360+
#####################################################################
361+
# MQTT Broker Management
362+
#####################################################################
363+
364+
# Certificate paths for broker TLS
365+
CERTS_DIR := $(CURDIR)/test/service/.certs
366+
ENV_FILE := $(CURDIR)/test/service/.env
367+
368+
generate-certs:
369+
@if [ ! -f "$(CERTS_DIR)/ca.crt" ]; then \
370+
echo "Generating TLS certificates..."; \
371+
python3 -m venv test/service/.venv 2>/dev/null || true; \
372+
test/service/.venv/bin/pip install -q cryptography; \
373+
cd test/service && .venv/bin/python3 -m utils.generate_certs \
374+
$(CERTS_DIR) --env-file $(ENV_FILE); \
375+
else \
376+
echo "✓ Certificates already exist in $(CERTS_DIR)"; \
377+
fi
378+
379+
broker-start: generate-certs
380+
@cd test/service && docker compose up -d broker
381+
@sleep 1
382+
@echo "✓ Broker running on port $$(cd test/service && docker compose port broker 1883 | cut -d: -f2)"
383+
384+
broker-stop:
385+
@cd test/service && docker compose down
386+
@echo "✓ Broker stopped"
387+
388+
#####################################################################
389+
# MQTT Manual Testing
390+
#####################################################################
391+
392+
MQTT_DETECTION_TOPIC := scenescape/data/camera/test-cam
393+
MQTT_TRACK_TOPIC := scenescape/data/scene/\#
394+
395+
mqtt-subscribe:
396+
@echo "Subscribing to tracks on $(TRACKER_MQTT_HOST):$(TRACKER_MQTT_PORT)..."
397+
mosquitto_sub -h $(TRACKER_MQTT_HOST) -p $(TRACKER_MQTT_PORT) -t '$(MQTT_TRACK_TOPIC)' -v
398+
399+
mqtt-publish:
400+
@echo "Publishing detection to $(TRACKER_MQTT_HOST):$(TRACKER_MQTT_PORT)..."
401+
mosquitto_pub -h $(TRACKER_MQTT_HOST) -p $(TRACKER_MQTT_PORT) -t '$(MQTT_DETECTION_TOPIC)' \
402+
-m '{"id":"test-cam","timestamp":"$(shell date -u +%Y-%m-%dT%H:%M:%S.000Z)","objects":{"person":[{"bounding_box_px":{"x":100,"y":50,"width":80,"height":200}}]}}'
403+
@echo "✓ Detection published"
404+
342405
#####################################################################
343406
# Clean targets
344407
#####################################################################
345408

346409
# Override common.mk clean to also remove local build directories
347410
clean:
348-
rm -rf build* test/service/.venv .pytest_cache
411+
-@cd test/service && docker compose down 2>/dev/null || true
412+
rm -rf build* test/service/.venv test/service/.certs test/service/.env .pytest_cache
349413
-docker rmi $(IMAGE):$(VERSION) $(IMAGE):latest 2>/dev/null || true
350414
-rm -f $(BUILD_DIR)/$(IMAGE)-*deps.txt $(LOG_FILE) 2>/dev/null || true

tracker/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ make install-tools
2424
# Coverage tools (optional, for local coverage reports)
2525
pipx install gcovr
2626
sudo apt-get install -y lcov
27+
28+
# MQTT client tools (optional, for manual testing)
29+
sudo apt-get install -y mosquitto-clients
2730
```
2831

2932
#### Build

tracker/conanfile.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
[requires]
55
quill/11.0.2
66
cli11/2.6.0
7-
simdjson/4.2.2
87
cpp-httplib/0.28.0
98
rapidjson/cci.20230929
109
gtest/1.17.0
1110
opencv/4.12.0
1211
eigen/3.4.0
12+
paho-mqtt-cpp/1.5.3
1313

1414
[generators]
1515
CMakeDeps

tracker/inc/config_loader.hpp

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,95 @@
44
#pragma once
55

66
#include <filesystem>
7+
#include <optional>
78
#include <string>
89

910
namespace tracker {
1011

12+
/**
13+
* @brief TLS certificate settings for secure connections.
14+
*/
15+
struct TlsConfig {
16+
std::string ca_cert_path;
17+
std::string client_cert_path;
18+
std::string client_key_path;
19+
bool verify_server = true;
20+
};
21+
22+
/**
23+
* @brief MQTT broker connection settings.
24+
*/
25+
struct MqttConfig {
26+
std::string host;
27+
int port;
28+
bool insecure = false;
29+
std::optional<TlsConfig> tls;
30+
};
31+
32+
/**
33+
* @brief Health check HTTP server settings.
34+
*/
35+
struct HealthcheckConfig {
36+
int port = 8080;
37+
};
38+
39+
/**
40+
* @brief Tracker service settings.
41+
*/
42+
struct TrackerConfig {
43+
HealthcheckConfig healthcheck;
44+
bool schema_validation = true;
45+
};
46+
47+
/**
48+
* @brief External service connections.
49+
*/
50+
struct InfrastructureConfig {
51+
MqttConfig mqtt;
52+
TrackerConfig tracker;
53+
};
54+
55+
/**
56+
* @brief Logging configuration.
57+
*/
58+
struct LoggingConfig {
59+
std::string level = "info";
60+
};
61+
62+
/**
63+
* @brief Observability settings.
64+
*/
65+
struct ObservabilityConfig {
66+
LoggingConfig logging;
67+
};
68+
1169
/**
1270
* @brief Service configuration loaded from JSON config file.
1371
*
1472
* Values can be overridden by environment variables with TRACKER_ prefix.
1573
*/
1674
struct ServiceConfig {
17-
std::string log_level;
18-
int healthcheck_port;
75+
InfrastructureConfig infrastructure;
76+
ObservabilityConfig observability;
1977
};
2078

2179
/// JSON Pointer paths (RFC6901) for extracting ServiceConfig values
2280
namespace json {
23-
constexpr char LOG_LEVEL[] = "/observability/logging/level";
24-
constexpr char HEALTHCHECK_PORT[] = "/infrastructure/tracker/healthcheck/port";
81+
constexpr char OBSERVABILITY_LOGGING_LEVEL[] = "/observability/logging/level";
82+
constexpr char INFRASTRUCTURE_TRACKER_HEALTHCHECK_PORT[] =
83+
"/infrastructure/tracker/healthcheck/port";
84+
constexpr char INFRASTRUCTURE_TRACKER_SCHEMA_VALIDATION[] =
85+
"/infrastructure/tracker/schema_validation";
86+
constexpr char INFRASTRUCTURE_MQTT_HOST[] = "/infrastructure/mqtt/host";
87+
constexpr char INFRASTRUCTURE_MQTT_PORT[] = "/infrastructure/mqtt/port";
88+
constexpr char INFRASTRUCTURE_MQTT_INSECURE[] = "/infrastructure/mqtt/insecure";
89+
constexpr char INFRASTRUCTURE_MQTT_TLS[] = "/infrastructure/mqtt/tls";
90+
constexpr char INFRASTRUCTURE_MQTT_TLS_CA_CERT_PATH[] = "/infrastructure/mqtt/tls/ca_cert_path";
91+
constexpr char INFRASTRUCTURE_MQTT_TLS_CLIENT_CERT_PATH[] =
92+
"/infrastructure/mqtt/tls/client_cert_path";
93+
constexpr char INFRASTRUCTURE_MQTT_TLS_CLIENT_KEY_PATH[] =
94+
"/infrastructure/mqtt/tls/client_key_path";
95+
constexpr char INFRASTRUCTURE_MQTT_TLS_VERIFY_SERVER[] = "/infrastructure/mqtt/tls/verify_server";
2596
} // namespace json
2697

2798
/**

tracker/inc/env_vars.hpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,29 @@ constexpr const char* LOG_LEVEL = "TRACKER_LOG_LEVEL";
1818
/// Environment variable for overriding healthcheck server port (1024-65535)
1919
constexpr const char* HEALTHCHECK_PORT = "TRACKER_HEALTHCHECK_PORT";
2020

21+
/// Environment variable for overriding MQTT broker host
22+
constexpr const char* MQTT_HOST = "TRACKER_MQTT_HOST";
23+
24+
/// Environment variable for overriding MQTT broker port (1-65535)
25+
constexpr const char* MQTT_PORT = "TRACKER_MQTT_PORT";
26+
27+
/// Environment variable for overriding MQTT insecure mode (true/false)
28+
constexpr const char* MQTT_INSECURE = "TRACKER_MQTT_INSECURE";
29+
30+
/// Environment variable for overriding MQTT TLS CA certificate path
31+
constexpr const char* MQTT_TLS_CA_CERT = "TRACKER_MQTT_TLS_CA_CERT";
32+
33+
/// Environment variable for overriding MQTT TLS client certificate path
34+
constexpr const char* MQTT_TLS_CLIENT_CERT = "TRACKER_MQTT_TLS_CLIENT_CERT";
35+
36+
/// Environment variable for overriding MQTT TLS client key path
37+
constexpr const char* MQTT_TLS_CLIENT_KEY = "TRACKER_MQTT_TLS_CLIENT_KEY";
38+
39+
/// Environment variable for overriding MQTT TLS server verification (true/false)
40+
constexpr const char* MQTT_TLS_VERIFY_SERVER = "TRACKER_MQTT_TLS_VERIFY_SERVER";
41+
42+
/// Environment variable for enabling/disabling JSON schema validation for MQTT messages
43+
/// (true/false)
44+
constexpr const char* MQTT_SCHEMA_VALIDATION = "TRACKER_MQTT_SCHEMA_VALIDATION";
45+
2146
} // namespace tracker::env

tracker/inc/logger.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ class Logger {
206206
static void log_warn(const LogEntry& entry);
207207
static void log_error(const LogEntry& entry);
208208

209+
// Check if debug logging is enabled (for conditional expensive computations)
210+
[[nodiscard]] static bool should_log_debug();
211+
209212
private:
210213
Logger() = default;
211214
~Logger() = default;

0 commit comments

Comments
 (0)