#!/usr/bin/env bash # run.sh – Build UDPStreamer and launch the test MARTe2 application. # # Usage: # ./run.sh # run MARTe2 app only # ./run.sh --webui # also start the WebUI Go client in the background # ./run.sh --nativeui # also start the NativeUI ImGui client in the background # ./run.sh --qtui # also start the NativeUI Qt client in the background # ./run.sh --help # show this message # # The clients are started with three sources: # Streamer @ 127.0.0.1:44500 (scalar signals, PacketTime, 1 kHz) # FastStreamer @ 127.0.0.1:44501 (packed arrays, FirstSample/LastSample, 5 kHz) # FullArrStreamer @ 127.0.0.1:44502 (packed arrays, FullArray, 5 kHz) # # Prerequisites: # - marte_env.sh must be present in the repo root (sets MARTe2_DIR, etc.) # - MARTe2 and MARTe2-components must already be built # # The script resolves all paths relative to the repo root so it can be # called from any working directory. set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" # ── Parse arguments ────────────────────────────────────────────────────────── START_WEBUI=0 START_NATIVEUI=0 START_QTUI=0 for arg in "$@"; do case "$arg" in --webui) START_WEBUI=1 ;; --nativeui) START_NATIVEUI=1 ;; --qtui) START_QTUI=1 ;; --help|-h) sed -n '2,21p' "$0" exit 0 ;; esac done # ── Load MARTe2 environment ────────────────────────────────────────────────── ENV_SCRIPT="${REPO_ROOT}/marte_env.sh" if [ ! -f "${ENV_SCRIPT}" ]; then echo "ERROR: ${ENV_SCRIPT} not found." >&2 exit 1 fi # shellcheck source=/dev/null source "${ENV_SCRIPT}" if [ -z "${MARTe2_DIR}" ]; then echo "ERROR: MARTe2_DIR is not set after sourcing marte_env.sh." >&2 exit 1 fi # ── Build components ───────────────────────────────────────────────────────── TARGET=x86-linux UDPSTREAMER_SRC="${REPO_ROOT}/Source/Components/DataSources/UDPStreamer" UDPSTREAMER_LIB="${REPO_ROOT}/Build/${TARGET}/Components/DataSources/UDPStreamer" SINEARRAYGAM_SRC="${REPO_ROOT}/Source/Components/GAMs/SineArrayGAM" SINEARRAYGAM_LIB="${REPO_ROOT}/Build/${TARGET}/Components/GAMs/SineArrayGAM" TIMEARRAYGAM_SRC="${REPO_ROOT}/Source/Components/GAMs/TimeArrayGAM" TIMEARRAYGAM_LIB="${REPO_ROOT}/Build/${TARGET}/Components/GAMs/TimeArrayGAM" echo "==> Building UDPStreamer (TARGET=${TARGET})..." make -C "${UDPSTREAMER_SRC}" \ -f Makefile.gcc \ TARGET="${TARGET}" \ 2>&1 | tail -5 echo "==> Building SineArrayGAM (TARGET=${TARGET})..." make -C "${SINEARRAYGAM_SRC}" \ -f Makefile.gcc \ TARGET="${TARGET}" \ 2>&1 | tail -5 echo "==> Building TimeArrayGAM (TARGET=${TARGET})..." make -C "${TIMEARRAYGAM_SRC}" \ -f Makefile.gcc \ TARGET="${TARGET}" \ 2>&1 | tail -5 echo "==> Build done." # ── Build WebUI binary (if requested and not already built) ────────────────── WEBUI_DIR="${REPO_ROOT}/Client/WebUI" WEBUI_BIN="${WEBUI_DIR}/udpstreamer-webui" if [ "${START_WEBUI}" -eq 1 ] && [ ! -x "${WEBUI_BIN}" ]; then echo "==> Building WebUI..." (cd "${WEBUI_DIR}" && go build -o udpstreamer-webui ./...) echo "==> WebUI build done." fi # ── Build NativeUI (ImGui) binary (if requested and not already built) ─────── NATIVEUI_DIR="${REPO_ROOT}/Client/NativeUI" NATIVEUI_BUILD="${NATIVEUI_DIR}/build" NATIVEUI_BIN="${NATIVEUI_BUILD}/daq_viewer" if [ "${START_NATIVEUI}" -eq 1 ]; then if [ ! -x "${NATIVEUI_BIN}" ]; then echo "==> Building NativeUI/ImGui (cmake)..." cmake -S "${NATIVEUI_DIR}" -B "${NATIVEUI_BUILD}" -DCMAKE_BUILD_TYPE=Release -Wno-dev cmake --build "${NATIVEUI_BUILD}" --parallel "$(nproc)" echo "==> NativeUI/ImGui build done." else # Rebuild if sources are newer than the binary if find "${NATIVEUI_DIR}/src" -name '*.cpp' -o -name '*.h' \ | xargs ls -t 2>/dev/null | head -1 \ | xargs -I{} test {} -nt "${NATIVEUI_BIN}" 2>/dev/null; then echo "==> Sources changed — rebuilding NativeUI/ImGui..." cmake --build "${NATIVEUI_BUILD}" --parallel "$(nproc)" echo "==> NativeUI/ImGui rebuild done." fi fi fi # ── Build NativeUI-Qt binary (if requested and not already built) ───────────── QTUI_DIR="${REPO_ROOT}/Client/NativeUI-Qt" QTUI_BUILD="${QTUI_DIR}/build" QTUI_BIN="${QTUI_BUILD}/daq_viewer" if [ "${START_QTUI}" -eq 1 ]; then if [ ! -x "${QTUI_BIN}" ]; then echo "==> Building NativeUI/Qt (cmake)..." cmake -S "${QTUI_DIR}" -B "${QTUI_BUILD}" -DCMAKE_BUILD_TYPE=Release -Wno-dev cmake --build "${QTUI_BUILD}" --parallel "$(nproc)" echo "==> NativeUI/Qt build done." else # Rebuild if sources are newer than the binary if find "${QTUI_DIR}/src" "${REPO_ROOT}/Client/NativeUI/src" \ \( -name '*.cpp' -o -name '*.h' \) \ | xargs ls -t 2>/dev/null | head -1 \ | xargs -I{} test {} -nt "${QTUI_BIN}" 2>/dev/null; then echo "==> Sources changed — rebuilding NativeUI/Qt..." cmake --build "${QTUI_BUILD}" --parallel "$(nproc)" echo "==> NativeUI/Qt rebuild done." fi fi fi # ── Set LD_LIBRARY_PATH ─────────────────────────────────────────────────────── COMP="${MARTe2_Components_DIR}/Build/${TARGET}/Components" export LD_LIBRARY_PATH="\ ${UDPSTREAMER_LIB}:\ ${SINEARRAYGAM_LIB}:\ ${TIMEARRAYGAM_LIB}:\ ${MARTe2_DIR}/Build/${TARGET}/Core:\ ${COMP}/DataSources/LinuxTimer:\ ${COMP}/DataSources/LoggerDataSource:\ ${COMP}/GAMs/IOGAM:\ ${COMP}/GAMs/WaveformGAM:\ ${LD_LIBRARY_PATH}" echo "==> LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" # ── Create class-name symlinks for MARTe2 auto-loader ──────────────────────── WAVEFORM_DIR="${COMP}/GAMs/WaveformGAM" for cls in WaveformSin WaveformChirp WaveformPointsDef; do target="${WAVEFORM_DIR}/${cls}.so" if [ ! -e "${target}" ]; then ln -sf "${WAVEFORM_DIR}/WaveformGAM.so" "${target}" fi done # ── Optionally start WebUI ──────────────────────────────────────────────────── WEBUI_PID="" if [ "${START_WEBUI}" -eq 1 ]; then echo "==> Starting WebUI on http://localhost:8080..." "${WEBUI_BIN}" \ --source "Streamer@127.0.0.1:44500/239.0.0.1:44503" \ --source "FastStreamer@127.0.0.1:44501" \ --source "FullArrStreamer@127.0.0.1:44502" \ --listen :8080 & WEBUI_PID=$! echo "==> WebUI PID ${WEBUI_PID}" fi # ── Optionally start NativeUI (ImGui) ──────────────────────────────────────── NATIVEUI_PID="" if [ "${START_NATIVEUI}" -eq 1 ]; then if [ ! -x "${NATIVEUI_BIN}" ]; then echo "ERROR: NativeUI/ImGui binary not found at ${NATIVEUI_BIN}" >&2 exit 1 fi echo "==> Starting NativeUI/ImGui..." "${NATIVEUI_BIN}" \ "Streamer@127.0.0.1:44500" \ "FastStreamer@127.0.0.1:44501" \ "FullArrStreamer@127.0.0.1:44502" & NATIVEUI_PID=$! echo "==> NativeUI/ImGui PID ${NATIVEUI_PID}" fi # ── Optionally start NativeUI-Qt ────────────────────────────────────────────── QTUI_PID="" if [ "${START_QTUI}" -eq 1 ]; then if [ ! -x "${QTUI_BIN}" ]; then echo "ERROR: NativeUI/Qt binary not found at ${QTUI_BIN}" >&2 exit 1 fi echo "==> Starting NativeUI/Qt..." "${QTUI_BIN}" \ "Streamer@127.0.0.1:44500" \ "FastStreamer@127.0.0.1:44501" \ "FullArrStreamer@127.0.0.1:44502" & QTUI_PID=$! echo "==> NativeUI/Qt PID ${QTUI_PID}" fi # ── Launch MARTe2 application ───────────────────────────────────────────────── MARTE_APP="${MARTe2_DIR}/Build/${TARGET}/App/MARTeApp.ex" CFG="${SCRIPT_DIR}/TestApp.cfg" if [ ! -x "${MARTE_APP}" ]; then echo "ERROR: MARTeApp.ex not found at ${MARTE_APP}" >&2 exit 1 fi echo "==> Starting MARTe2 application (state=Running)..." echo "==> Thread1: scalar signals 1 kHz → port 44500" echo "==> Thread2: packed arrays 5 kHz → port 44501 (FirstSample / LastSample)" echo "==> Thread3: FullArray arrays 5 kHz → port 44502 (FullArray)" echo "==> Press Ctrl+C to stop." echo "" cleanup() { echo "" echo "==> Stopping..." [ -n "${WEBUI_PID}" ] && kill -0 "${WEBUI_PID}" 2>/dev/null && kill "${WEBUI_PID}" [ -n "${NATIVEUI_PID}" ] && kill -0 "${NATIVEUI_PID}" 2>/dev/null && kill "${NATIVEUI_PID}" [ -n "${QTUI_PID}" ] && kill -0 "${QTUI_PID}" 2>/dev/null && kill "${QTUI_PID}" } trap cleanup EXIT INT TERM "${MARTE_APP}" \ -l RealTimeLoader \ -f "${CFG}" \ -s Running