{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "provenance": [], "authorship_tag": "ABX9TyM6ZfhRPbrd/iTT3jekChL3", "include_colab_link": true }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python" } }, "cells": [ { "cell_type": "markdown", "metadata": { "id": "view-in-github", "colab_type": "text" }, "source": [ "\"Open" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "RlvccJ0kvDVB" }, "outputs": [], "source": [ "# === Cell 0: ngrok auth token ===\n", "# To get your ngrok auth token:\n", "# 1. Sign up/log in at https://ngrok.com/\n", "# 2. Go to 'Your Authtoken' in the dashboard: https://dashboard.ngrok.com/get-started/your-authtoken\n", "# 3. Copy your authtoken and paste it below.\n", "NGROK_AUTH_TOKEN = \"YOUR_NGROK_AUTH_TOKEN_HERE\"\n", "\n", "if NGROK_AUTH_TOKEN == \"YOUR_NGROK_AUTH_TOKEN_HERE\":\n", " print(\"⚠️ Paste your ngrok token into NGROK_AUTH_TOKEN, then re-run this cell.\")\n", "else:\n", " print(\"✅ ngrok token set (showing prefix only):\", NGROK_AUTH_TOKEN[:10] + \"...\")" ] }, { "cell_type": "code", "source": [ "# === Cell 1: install deps ===\n", "!pip -q install pyngrok requests\n", "\n", "print(\"✅ Installed pyngrok + requests\")" ], "metadata": { "id": "Bg0glm4oPUmd" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "source": [ "# === Cell 2: clone repo ===\n", "import os, subprocess, textwrap, sys\n", "\n", "REPO_URL = \"https://github.com/ruvnet/RuView\"\n", "REPO_DIR = \"RuView\"\n", "\n", "if not os.path.exists(REPO_DIR):\n", " !git clone --depth 1 {REPO_URL} {REPO_DIR}\n", "else:\n", " print(\"✅ Repo already cloned\")\n", "\n", "print(\"📁 Repo dir:\", os.path.abspath(REPO_DIR))" ], "metadata": { "id": "T4HLDmx-Pn7a" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "source": [ "# === Cell 3: find likely server entrypoints ===\n", "import os, re, pathlib, json\n", "\n", "root = pathlib.Path(\"RuView\")\n", "\n", "candidates = []\n", "\n", "# Common patterns\n", "patterns = [\n", " (\"Cargo.toml\", r\"\\[package\\]\"),\n", " (\"docker\", r\"Dockerfile\"),\n", " (\"python-fastapi\", r\"FastAPI\\(\"),\n", " (\"uvicorn\", r\"uvicorn\"),\n", " (\"axum\", r\"axum\"),\n", " (\"rocket\", r\"rocket::\"),\n", "]\n", "\n", "# Scan a subset of files (avoid huge scan)\n", "for p in root.rglob(\"*\"):\n", " if p.is_dir():\n", " continue\n", " if p.suffix.lower() not in [\".md\", \".toml\", \".rs\", \".py\", \".yml\", \".yaml\", \".json\", \".sh\", \".ts\", \".js\"]:\n", " continue\n", " # Skip big files\n", " try:\n", " if p.stat().st_size > 2_000_000:\n", " continue\n", " txt = p.read_text(errors=\"ignore\")\n", " except Exception:\n", " continue\n", "\n", " hit = False\n", " for tag, rx in patterns:\n", " if re.search(rx, txt):\n", " hit = True\n", " break\n", " if hit:\n", " candidates.append(str(p))\n", "\n", "# Print a small curated list (top 60)\n", "print(\"Found candidate files (showing up to 60):\")\n", "for f in candidates[:60]:\n", " print(\" -\", f)\n", "\n", "print(\"\\nNext: we will choose the correct server command based on what we find.\")" ], "metadata": { "id": "tBx6uZ_oQd9q" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "source": [ "# === Cell 4: run cargo from the Rust workspace root (v2/) ===\n", "\n", "import os, shutil, subprocess\n", "\n", "# Ensure current process sees cargo in PATH (even if shell wasn't restarted)\n", "if shutil.which(\"cargo\") is None:\n", " # rustup wrote this file; sourcing it would normally happen in a shell\n", " cargo_env = os.path.expanduser(\"~/.cargo/env\")\n", " if os.path.exists(cargo_env):\n", " # Minimal PATH fix for this Python process\n", " os.environ[\"PATH\"] = os.path.expanduser(\"~/.cargo/bin\") + \":\" + os.environ.get(\"PATH\", \"\")\n", "print(\"cargo:\", shutil.which(\"cargo\"))\n", "\n", "# Move into the Rust workspace directory\n", "%cd /content/RuView/v2\n", "\n", "# Confirm Cargo.toml exists here\n", "!ls -la | head -n 50\n", "!test -f Cargo.toml && echo \"✅ Found v2/Cargo.toml\" || (echo \"❌ Cargo.toml still missing\" && exit 1)\n", "\n", "print(\"\\n--- Checking sensing-server help ---\")\n", "!cargo run -q -p wifi-densepose-sensing-server -- --help | head -n 120" ], "metadata": { "collapsed": true, "id": "OJNZLiILXLTK" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "source": [ "# === Cell 5: hardcode SENSING_ALLOWED_HOSTS for ngrok ===\n", "\n", "import subprocess, time, socket, threading, shlex, os\n", "\n", "HTTP_PORT = 3000\n", "BIND_ADDR = \"0.0.0.0\"\n", "UI_PATH = \"../ui\"\n", "\n", "# Put your ngrok hostname here (NO https://, just host).\n", "# After running Cell 6 with your NGROK_AUTH_TOKEN, you will see a public URL.\n", "# For example, if the public URL is 'https://rewire-confirm-humongous.ngrok-free.dev',\n", "# then your NGROK_HOST should be 'rewire-confirm-humongous.ngrok-free.dev'.\n", "NGROK_HOST = \"YOUR_NGROK_HOST_HERE\"\n", "\n", "def is_port_open(port, host=\"127.0.0.1\"):\n", " s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n", " try:\n", " s.settimeout(0.5)\n", " return s.connect_ex((host, port)) == 0\n", " finally:\n", " s.close()\n", "\n", "# Hardcode all common Host header variants that may reach the server via ngrok/proxies\n", "SENSING_ALLOWED_HOSTS = \",\".join([\n", " NGROK_HOST,\n", " f\"{NGROK_HOST}:443\",\n", " f\"{NGROK_HOST}:80\",\n", " f\"{NGROK_HOST}:{HTTP_PORT}\",\n", " \"localhost\",\n", " f\"localhost:{HTTP_PORT}\",\n", " \"127.0.0.1\",\n", " f\"127.0.0.1:{HTTP_PORT}\",\n", "])\n", "\n", "env = os.environ.copy()\n", "env[\"SENSING_ALLOWED_HOSTS\"] = SENSING_ALLOWED_HOSTS\n", "\n", "cmd = [\n", " \"cargo\", \"run\", \"-q\", \"-p\", \"wifi-densepose-sensing-server\", \"--\",\n", " \"--bind-addr\", BIND_ADDR,\n", " \"--http-port\", str(HTTP_PORT),\n", " \"--ui-path\", UI_PATH,\n", " \"--source\", \"simulate\",\n", "]\n", "\n", "print(\"Starting sensing-server:\\n \", \" \".join(shlex.quote(x) for x in cmd))\n", "print(\"SENSING_ALLOWED_HOSTS =\", env[\"SENSING_ALLOWED_HOSTS\"])\n", "\n", "server_proc = subprocess.Popen(\n", " cmd,\n", " stdout=subprocess.PIPE,\n", " stderr=subprocess.STDOUT,\n", " text=True,\n", " bufsize=1,\n", " env=env\n", ")\n", "\n", "# Stream logs\n", "log_lines = []\n", "def pump_logs():\n", " for line in server_proc.stdout:\n", " line = line.rstrip()\n", " log_lines.append(line)\n", " print(line)\n", "\n", "t = threading.Thread(target=pump_logs, daemon=True)\n", "t.start()\n", "\n", "print(f\"\\nWaiting for HTTP listener on 127.0.0.1:{HTTP_PORT} ...\")\n", "for i in range(60):\n", " if is_port_open(HTTP_PORT, \"127.0.0.1\"):\n", " print(f\"\\n✅ Server is listening at http://127.0.0.1:{HTTP_PORT}\")\n", " break\n", " if i % 10 == 0:\n", " print(f\" ... {i}/60 seconds\")\n", " time.sleep(1)" ], "metadata": { "id": "-qGg5k0ZXNrW" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "source": [ "# === Cell 6: ngrok tunnel ===\n", "from pyngrok import ngrok\n", "\n", "if NGROK_AUTH_TOKEN != \"YOUR_NGROK_AUTH_TOKEN_HERE\":\n", " ngrok.set_auth_token(NGROK_AUTH_TOKEN)\n", " public_url = ngrok.connect(3000, \"http\")\n", " print(\"✅ Public URL:\", public_url)\n", "else:\n", " print(\"⚠️ No token set; skipping ngrok\")" ], "metadata": { "id": "dmzklhVuXPvc" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "source": [ "# === Cell 7: test the correct endpoints for wifi-densepose-sensing-server ===\n", "import requests, json\n", "\n", "base = \"http://127.0.0.1:3000\"\n", "\n", "paths = [\n", " \"/health\",\n", " \"/ui/index.html\",\n", "\n", " # Pose + zones\n", " \"/api/v1/pose/current\",\n", " \"/api/v1/pose/stats\",\n", " \"/api/v1/pose/zones/summary\",\n", "\n", " # Vital signs\n", " \"/api/v1/vital-signs\",\n", " \"/api/v1/edge-vitals\",\n", "\n", " # Stream + introspection\n", " \"/api/v1/stream/status\",\n", " \"/api/v1/introspection/snapshot\",\n", "\n", " # Model info (may be empty if no model loaded)\n", " \"/api/v1/model/info\",\n", " \"/api/v1/models\",\n", " \"/api/v1/models/active\",\n", "]\n", "\n", "for path in paths:\n", " url = base + path\n", " try:\n", " r = requests.get(url, timeout=8)\n", " print(f\"{path} -> {r.status_code}\")\n", "\n", " ctype = r.headers.get(\"content-type\", \"\")\n", " if \"application/json\" in ctype:\n", " print(\" \", json.dumps(r.json(), indent=2)[:1200])\n", " else:\n", " # show a small snippet for HTML/text\n", " print(\" \", r.text[:200].replace(\"\\n\", \" \") + (\"...\" if len(r.text) > 200 else \"\"))\n", " except Exception as e:\n", " print(f\"{path} -> ERROR: {type(e).__name__}: {str(e)[:200]}\")\n", " print()" ], "metadata": { "id": "xAMHOUOiXR_D" }, "execution_count": null, "outputs": [] } ] }