diff --git a/hermes/bin/hhb b/hermes/bin/hhb index 36e2677..86c00e6 100755 --- a/hermes/bin/hhb +++ b/hermes/bin/hhb @@ -2,14 +2,13 @@ # ────────────────────────────────────────────────────────── # hhb — Hermes-Houdini Bridge Client # Sends Python/hou commands to a running Houdini session -# via SSH + hcommand. +# via SSH + hcommand. Results returned via temp file. # ────────────────────────────────────────────────────────── set -euo pipefail HOST="${HHB_HOST:-niklas@192.168.178.39}" PORT="${HHB_PORT:-12345}" HCOMMAND="${HHB_HCOMMAND:-/opt/hfs21.0/bin/hcommand}" -WORKSPACE="${HHB_WORKSPACE:-/opt/data/projects/hermes-houdini-bridge}" usage() { cat <<'EOF' @@ -17,49 +16,51 @@ Usage: hhb [args] Commands: eval Execute Python code in the running Houdini session. - Example: hhb eval "print(hou.selectedNodes())" - script Send a Python script file to Houdini and execute it. - Example: hhb script ./examples/create_pyro_setup.py - get-selected Print paths and types of selected nodes. get-param Get value of a parameter on the first selected node. set-param Set a parameter on the first selected node. get-inputs Print input connections of the first selected node. status Check if the bridge port is open. help Show this help. - EOF exit 0 } -# ── Helpers ────────────────────────────────────────────── +# ── Core: write Python script, execute, read back output ─ -run_remote_python() { - # Write Python code to a temp file, execute via hcommand. - # This avoids quoting hell with complex Python snippets. +run_houdini_python() { + # $1: Python code (as a string) + # Writes code to /tmp/hhb_script.py, executes via hcommand, + # reads output from /tmp/hhb_out.txt local python_code="$1" - local tmpfile="/tmp/hhb_$$.py" + local sid="$$" - # Upload script - printf '%s' "$python_code" | ssh "$HOST" "cat > $tmpfile" + # Upload the script + printf '%s' "$python_code" | ssh "$HOST" "cat > /tmp/hhb_script_${sid}.py" - # Execute via hscript's python command — reads file and execs - local output - output=$(ssh "$HOST" \ - "$HCOMMAND $PORT \"python exec(open('$tmpfile').read())\"" 2>&1) || { - local rc=$? - ssh "$HOST" "rm -f $tmpfile" 2>/dev/null - echo "hhb: hcommand failed (exit $rc)" >&2 - echo "$output" >&2 - return $rc - } + # Execute via hcommand + ssh "$HOST" "$HCOMMAND $PORT 'python /tmp/hhb_script_${sid}.py'" 2>/dev/null || true + + # Read output file + ssh "$HOST" "cat /tmp/hhb_out_${sid}.txt 2>/dev/null" || echo "" # Cleanup - ssh "$HOST" "rm -f $tmpfile" 2>/dev/null + ssh "$HOST" "rm -f /tmp/hhb_script_${sid}.py /tmp/hhb_out_${sid}.txt" 2>/dev/null || true +} - # hcommand output has a prefix line like "-> foobar", strip it - echo "$output" | sed 's/^->\s*//' +# Wrap user code to capture output via temp file +wrap_python() { + local code="$1" + local sid="$$" + cat <"; exit 1; } - run_remote_python "$*" + local sid="$$" + local code + code=$(cat <"; exit 1; } local script_path="$1" + local sid="$$" [[ -f "$script_path" ]] || { echo "File not found: $script_path"; exit 1; } - scp -q "$script_path" "$HOST:/tmp/hhb_script_$$.py" - local output - output=$(ssh "$HOST" \ - "$HCOMMAND $PORT \"python exec(open('/tmp/hhb_script_$$.py').read())\"" 2>&1) || { - local rc=$? - ssh "$HOST" "rm -f /tmp/hhb_script_$$.py" 2>/dev/null - echo "hhb: hcommand failed (exit $rc)" >&2 - echo "$output" >&2 - return $rc - } - ssh "$HOST" "rm -f /tmp/hhb_script_$$.py" 2>/dev/null - echo "$output" | sed 's/^->\s*//' + # Read the script, wrap in output capture + local code + code=$(cat "$script_path") + local wrapped + wrapped=$(cat <"; exit 1; } local parm="$1" - run_remote_python " -import hou + local sid="$$" + local code + code=$(cat < "; exit 1; } local parm="$1" local val="$2" - run_remote_python " -import hou + local sid="$$" + local code + code=$(cat <