Initial go port of epics

This commit is contained in:
Martino Ferrari
2026-04-28 00:09:22 +02:00
parent 47e481a461
commit 6e51ffc5e1
28 changed files with 5634 additions and 178 deletions
+66 -52
View File
@@ -5,9 +5,11 @@
# bash workspace/run.sh
#
# Requirements:
# • EPICS Base installed (EPICS_BASE set, or auto-detected below)
# • softIoc binary available
# • uopi built with EPICS support (script builds it if missing)
# • 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
@@ -15,32 +17,24 @@ PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
WORKSPACE="$PROJECT_ROOT/workspace"
BINARY="$PROJECT_ROOT/dist/uopi"
# ── Locate EPICS Base ─────────────────────────────────────────────────────────
# ── Locate EPICS tools ────────────────────────────────────────────────────────
if [ -z "${EPICS_BASE:-}" ]; then
for candidate in \
/usr/lib/epics \
/usr/local/epics \
/opt/epics/base \
/opt/epics; do
if [ -f "$candidate/include/cadef.h" ]; then
export EPICS_BASE="$candidate"
break
fi
done
# 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 [ -z "${EPICS_BASE:-}" ]; then
echo "ERROR: EPICS_BASE is not set and could not be auto-detected."
echo " export EPICS_BASE=/path/to/epics/base"
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
# Detect architecture
EPICS_ARCH="${EPICS_ARCH:-$(ls "$EPICS_BASE/lib" | grep linux | head -1)}"
if [ -z "$EPICS_ARCH" ]; then
EPICS_ARCH="linux-x86_64"
fi
echo "softIoc: $(command -v softIoc)"
# ── Environment ───────────────────────────────────────────────────────────────
@@ -48,24 +42,17 @@ fi
export EPICS_CA_ADDR_LIST="127.0.0.1"
export EPICS_CA_AUTO_ADDR_LIST="NO"
# Ensure the EPICS shared libraries are found at runtime.
export LD_LIBRARY_PATH="$EPICS_BASE/lib/$EPICS_ARCH${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
# Make EPICS tools (softIoc, caget, caput…) available.
export PATH="$EPICS_BASE/bin/$EPICS_ARCH:$PATH"
# ── Locate softIoc ────────────────────────────────────────────────────────────
if ! command -v softIoc &>/dev/null; then
echo "ERROR: softIoc not found in $EPICS_BASE/bin/$EPICS_ARCH or PATH."
exit 1
fi
# Enable CA-level debug logging in uopi (set to "" to disable).
export UOPI_CA_DEBUG="${UOPI_CA_DEBUG:-1}"
# ── Build uopi ────────────────────────────────────────────────────────────────
echo "Building uopi with EPICS support..."
echo "Building uopi + catools..."
cd "$PROJECT_ROOT"
make backend-epics 2>&1
make backend 2>&1
echo ""
echo " catools: $PROJECT_ROOT/dist/catools"
echo " Usage: dist/catools caget UOPI:TICK"
echo ""
# ── Cleanup handler ───────────────────────────────────────────────────────────
@@ -85,39 +72,66 @@ trap cleanup EXIT INT TERM
pkill -x softIoc 2>/dev/null || true
# Give the OS a moment to release the CA port (5064/tcp+udp).
sleep 0.3
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 accept Channel Access connections (up to 10 s).
echo -n "Waiting for IOC to be ready"
# 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 caget -w 1 UOPI:TICK >/dev/null 2>&1; then
echo " OK"
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
if [ "$i" -eq 20 ]; then
echo ""
echo "ERROR: IOC did not become ready within 10 seconds."
echo "Check $WORKSPACE/softioc.log for details."
exit 1
fi
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:8080)..."
echo " Open the browser, switch to Edit mode, load workspace/data/epics_test.xml"
echo " or select it from the interface list in View mode."
echo " Press Ctrl-C to stop."
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"
+36
View File
@@ -1,2 +1,38 @@
Starting iocInit
iocRun: All initialization complete
CAS: request from 127.0.0.1:56104 => bad resource ID
CAS: Request from 127.0.0.1:56104 => cmmd=1 cid=0x2 type=25 count=1 postsize=16
CAS: Request from 127.0.0.1:56104 => available=0x1 N=0 paddr=(nil)
CAS: forcing disconnect from 127.0.0.1:56104
CAS: request from 127.0.0.1:56106 => bad resource ID
CAS: Request from 127.0.0.1:56106 => cmmd=1 cid=0x5 type=25 count=1 postsize=16
CAS: Request from 127.0.0.1:56106 => available=0x3 N=0 paddr=(nil)
CAS: forcing disconnect from 127.0.0.1:56106
CAS: request from 127.0.0.1:56120 => bad resource ID
CAS: Request from 127.0.0.1:56120 => cmmd=1 cid=0x8 type=25 count=1 postsize=16
CAS: Request from 127.0.0.1:56120 => available=0x6 N=0 paddr=(nil)
CAS: forcing disconnect from 127.0.0.1:56120
CAS: request from 127.0.0.1:56126 => bad resource ID
CAS: Request from 127.0.0.1:56126 => cmmd=1 cid=0xb type=25 count=1 postsize=16
CAS: Request from 127.0.0.1:56126 => available=0xa N=0 paddr=(nil)
CAS: forcing disconnect from 127.0.0.1:56126
CAS: request from 127.0.0.1:56130 => no memory to add subscription to db
CAS: Request from 127.0.0.1:56130 => cmmd=1 cid=0xe type=25 count=1 postsize=16
CAS: Request from 127.0.0.1:56130 => available=0xf N=0 paddr=0x7fae3800d838
CAS: forcing disconnect from 127.0.0.1:56130
CAS: request from 127.0.0.1:56132 => no memory to add subscription to db
CAS: Request from 127.0.0.1:56132 => cmmd=1 cid=0x10 type=25 count=1 postsize=16
CAS: Request from 127.0.0.1:56132 => available=0x11 N=0 paddr=0x7fae3800d768
CAS: forcing disconnect from 127.0.0.1:56132
CAS: request from 127.0.0.1:56144 => bad resource ID
CAS: Request from 127.0.0.1:56144 => cmmd=1 cid=0x10 type=25 count=1 postsize=16
CAS: Request from 127.0.0.1:56144 => available=0x17 N=0 paddr=(nil)
CAS: forcing disconnect from 127.0.0.1:56144
CAS: request from 127.0.0.1:56148 => bad resource ID
CAS: Request from 127.0.0.1:56148 => cmmd=1 cid=0x10 type=25 count=1 postsize=16
CAS: Request from 127.0.0.1:56148 => available=0x1d N=0 paddr=(nil)
CAS: forcing disconnect from 127.0.0.1:56148
CAS: request from 127.0.0.1:60292 => bad resource ID
CAS: Request from 127.0.0.1:60292 => cmmd=1 cid=0x10 type=25 count=1 postsize=16
CAS: Request from 127.0.0.1:60292 => available=0x24 N=0 paddr=(nil)
CAS: forcing disconnect from 127.0.0.1:60292