#!/usr/bin/env bash # workspace/run.sh — start softIOC + uopi for EPICS workspace testing # # Usage (from project root): # bash workspace/run.sh # # Requirements: # • EPICS Base installed (softIoc binary available in PATH or EPICS_BASE) # • uopi built (script builds it if missing) # # uopi connects to EPICS via its built-in pure-Go CA client — no libca needed. # Set UOPI_CA_DEBUG=1 (default below) to enable CA-level debug logging. set -euo pipefail PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" WORKSPACE="$PROJECT_ROOT/workspace" BINARY="$PROJECT_ROOT/dist/uopi" # ── Locate EPICS tools ──────────────────────────────────────────────────────── # If EPICS_BASE is set, add its bin directory to PATH automatically. if [ -n "${EPICS_BASE:-}" ]; then if [ -z "${EPICS_ARCH:-}" ]; then EPICS_ARCH="$(ls "$EPICS_BASE/bin" 2>/dev/null | grep -i linux | head -1 || true)" EPICS_ARCH="${EPICS_ARCH:-linux-x86_64}" fi export PATH="$EPICS_BASE/bin/$EPICS_ARCH:$PATH" echo "EPICS_BASE=$EPICS_BASE EPICS_ARCH=$EPICS_ARCH" fi if ! command -v softIoc &>/dev/null; then echo "ERROR: softIoc not found in PATH." echo " Set EPICS_BASE=/path/to/epics/base, or add softIoc to your PATH." exit 1 fi echo "softIoc: $(command -v softIoc)" # ── Environment ─────────────────────────────────────────────────────────────── # Point CA exclusively at the local IOC — no broadcast scanning. export EPICS_CA_ADDR_LIST="127.0.0.1" export EPICS_CA_AUTO_ADDR_LIST="NO" # Enable CA-level debug logging in uopi (set to "" to disable). export UOPI_CA_DEBUG="${UOPI_CA_DEBUG:-1}" # ── Build uopi ──────────────────────────────────────────────────────────────── echo "Building uopi + catools..." cd "$PROJECT_ROOT" make backend 2>&1 echo "" echo " catools: $PROJECT_ROOT/dist/catools" echo " Usage: dist/catools caget UOPI:TICK" echo "" # ── Cleanup handler ─────────────────────────────────────────────────────────── PIDS=() cleanup() { echo "" echo "Shutting down..." for pid in "${PIDS[@]:-}"; do kill "$pid" 2>/dev/null || true done wait 2>/dev/null || true } trap cleanup EXIT INT TERM # ── Kill any stale softIOC from a previous run ──────────────────────────────── pkill -x softIoc 2>/dev/null || true # Give the OS a moment to release the CA port (5064/tcp+udp). sleep 0.5 # ── Start softIOC ───────────────────────────────────────────────────────────── echo "Starting softIOC..." echo " DB: $WORKSPACE/softioc/uopi_test.db" echo " Log: $WORKSPACE/softioc.log" softIoc -S -d "$WORKSPACE/softioc/uopi_test.db" \ >"$WORKSPACE/softioc.log" 2>&1 & IOC_PID=$! PIDS+=("$IOC_PID") # Wait for the IOC to start listening on TCP 5064 (up to 10 s). # We probe with nc (netcat) first — no EPICS tools required. echo -n "Waiting for IOC port 5064" IOC_READY=0 for i in $(seq 1 20); do if nc -z 127.0.0.1 5064 2>/dev/null; then echo " OK (TCP 5064 open)" IOC_READY=1 break fi echo -n "." sleep 0.5 done if [ "$IOC_READY" -eq 0 ]; then echo "" echo "ERROR: IOC port 5064 not open after 10 seconds." echo "softIoc log:" cat "$WORKSPACE/softioc.log" || true exit 1 fi # Optional deeper check with caget if it's available. if command -v caget &>/dev/null; then echo -n "Verifying UOPI:TICK with caget" for i in $(seq 1 10); do if caget -w 1 UOPI:TICK >/dev/null 2>&1; then echo " OK" break fi echo -n "." sleep 0.5 if [ "$i" -eq 10 ]; then echo " (timeout — continuing anyway)" fi done else echo "caget not in PATH — skipping PV check (softIoc assumed ready)" sleep 1 fi # ── Start uopi ──────────────────────────────────────────────────────────────── echo "" echo "Starting uopi (http://localhost:8088)..." echo " UOPI_CA_DEBUG=$UOPI_CA_DEBUG" echo " Config: $WORKSPACE/uopi.toml" echo " Log will appear below. Press Ctrl-C to stop." echo "" cd "$PROJECT_ROOT" "$BINARY" -config "$WORKSPACE/uopi.toml"