|
25 | 25 | }, |
26 | 26 | { |
27 | 27 | "cell_type": "code", |
28 | | - "execution_count": null, |
29 | | - "metadata": {}, |
30 | | - "outputs": [], |
| 28 | + "execution_count": 1, |
| 29 | + "metadata": { |
| 30 | + "jupyter": { |
| 31 | + "source_hidden": true |
| 32 | + } |
| 33 | + }, |
| 34 | + "outputs": [ |
| 35 | + { |
| 36 | + "name": "stdout", |
| 37 | + "output_type": "stream", |
| 38 | + "text": [ |
| 39 | + "✅ Rio API client initialized\n", |
| 40 | + " Base URL: http://localhost:8000\n" |
| 41 | + ] |
| 42 | + } |
| 43 | + ], |
31 | 44 | "source": [ |
32 | 45 | "# Configuration\n", |
33 | 46 | "import os\n", |
|
42 | 55 | "import sys\n", |
43 | 56 | "from pathlib import Path\n", |
44 | 57 | "\n", |
45 | | - "# Add software/client to path for client import\n", |
46 | | - "# This works whether running from repo root or software/client/notebooks/\n", |
| 58 | + "# Add software/api/client to path for client import\n", |
| 59 | + "# This works whether running from repo root or software/api/client/notebooks/\n", |
47 | 60 | "repo_root = Path.cwd()\n", |
48 | | - "if (repo_root / \"software\" / \"client\").exists():\n", |
| 61 | + "if (repo_root / \"software\" / \"api\" / \"client\").exists():\n", |
49 | 62 | " # Running from repo root\n", |
50 | 63 | " sys.path.insert(0, str(repo_root / \"software\"))\n", |
51 | | - "elif (repo_root.parent.parent / \"software\" / \"client\").exists():\n", |
52 | | - " # Running from software/client/notebooks/\n", |
| 64 | + "elif (repo_root.parent.parent / \"software\" / \"api\" / \"client\").exists():\n", |
| 65 | + " # Running from software/api/client/notebooks/\n", |
53 | 66 | " sys.path.insert(0, str(repo_root.parent.parent))\n", |
54 | 67 | "else:\n", |
55 | 68 | " # Fallback: try to find software directory\n", |
56 | 69 | " for parent in repo_root.parents:\n", |
57 | | - " if (parent / \"software\" / \"client\").exists():\n", |
| 70 | + " if (parent / \"software\" / \"api\" / \"client\").exists():\n", |
58 | 71 | " sys.path.insert(0, str(parent / \"software\"))\n", |
59 | 72 | " break\n", |
60 | 73 | "\n", |
61 | | - "from client import RioClient, RioStreamClient\n", |
| 74 | + "from api.client import RioClient, RioStreamClient\n", |
62 | 75 | "import requests\n", |
63 | 76 | "import json\n", |
64 | 77 | "import time\n", |
|
72 | 85 | "client = RioClient(base_url=API_BASE_URL)\n", |
73 | 86 | "\n", |
74 | 87 | "print(\"✅ Rio API client initialized\")\n", |
75 | | - "print(f\" Base URL: {API_BASE_URL}\")\n" |
| 88 | + "print(f\" Base URL: {API_BASE_URL}\")" |
76 | 89 | ] |
77 | 90 | }, |
78 | 91 | { |
79 | 92 | "cell_type": "markdown", |
80 | | - "metadata": {}, |
| 93 | + "metadata": { |
| 94 | + "jp-MarkdownHeadingCollapsed": true |
| 95 | + }, |
81 | 96 | "source": [ |
82 | 97 | "## 1. System Health and Capabilities\n", |
83 | 98 | "\n", |
|
86 | 101 | }, |
87 | 102 | { |
88 | 103 | "cell_type": "code", |
89 | | - "execution_count": null, |
| 104 | + "execution_count": 2, |
90 | 105 | "metadata": {}, |
91 | | - "outputs": [], |
| 106 | + "outputs": [ |
| 107 | + { |
| 108 | + "name": "stdout", |
| 109 | + "output_type": "stream", |
| 110 | + "text": [ |
| 111 | + "Status: ok\n", |
| 112 | + "Simulation mode: True\n", |
| 113 | + "\n", |
| 114 | + "Available modules:\n", |
| 115 | + " ✅ flow: True\n", |
| 116 | + " ✅ pressure: True\n", |
| 117 | + " ✅ heater: True\n", |
| 118 | + " ❌ strobe: False\n", |
| 119 | + " ❌ camera: False\n", |
| 120 | + " ❌ droplet: False\n", |
| 121 | + " ✅ pump: True\n" |
| 122 | + ] |
| 123 | + } |
| 124 | + ], |
92 | 125 | "source": [ |
93 | 126 | "# Check health\n", |
94 | 127 | "health = client.health()\n", |
|
100 | 133 | "print(\"\\nAvailable modules:\")\n", |
101 | 134 | "for module, available in capabilities['modules'].items():\n", |
102 | 135 | " status = \"✅\" if available else \"❌\"\n", |
103 | | - " print(f\" {status} {module}: {available}\")\n" |
| 136 | + " print(f\" {status} {module}: {available}\")" |
104 | 137 | ] |
105 | 138 | }, |
106 | 139 | { |
107 | 140 | "cell_type": "markdown", |
108 | | - "metadata": {}, |
| 141 | + "metadata": { |
| 142 | + "jp-MarkdownHeadingCollapsed": true |
| 143 | + }, |
109 | 144 | "source": [ |
110 | 145 | "## 2. Channel Configuration\n", |
111 | 146 | "\n", |
|
140 | 175 | }, |
141 | 176 | { |
142 | 177 | "cell_type": "markdown", |
143 | | - "metadata": {}, |
| 178 | + "metadata": { |
| 179 | + "jp-MarkdownHeadingCollapsed": true |
| 180 | + }, |
144 | 181 | "source": [ |
145 | 182 | "## 3. Flow/Pressure Control\n", |
146 | 183 | "\n", |
|
174 | 211 | }, |
175 | 212 | { |
176 | 213 | "cell_type": "markdown", |
177 | | - "metadata": {}, |
| 214 | + "metadata": { |
| 215 | + "jp-MarkdownHeadingCollapsed": true |
| 216 | + }, |
178 | 217 | "source": [ |
179 | 218 | "## 4. Heater Control\n", |
180 | 219 | "\n", |
|
210 | 249 | }, |
211 | 250 | { |
212 | 251 | "cell_type": "markdown", |
213 | | - "metadata": {}, |
| 252 | + "metadata": { |
| 253 | + "jp-MarkdownHeadingCollapsed": true |
| 254 | + }, |
214 | 255 | "source": [ |
215 | 256 | "## 5. Camera Snapshot\n", |
216 | 257 | "\n", |
|
234 | 275 | }, |
235 | 276 | { |
236 | 277 | "cell_type": "markdown", |
237 | | - "metadata": {}, |
| 278 | + "metadata": { |
| 279 | + "jp-MarkdownHeadingCollapsed": true |
| 280 | + }, |
238 | 281 | "source": [ |
239 | 282 | "## 6. WebSocket Telemetry Streaming\n", |
240 | 283 | "\n", |
|
277 | 320 | }, |
278 | 321 | { |
279 | 322 | "cell_type": "markdown", |
280 | | - "metadata": {}, |
| 323 | + "metadata": { |
| 324 | + "jp-MarkdownHeadingCollapsed": true |
| 325 | + }, |
281 | 326 | "source": [ |
282 | 327 | "## 7. Plot Streaming Data\n", |
283 | 328 | "\n", |
|
332 | 377 | }, |
333 | 378 | { |
334 | 379 | "cell_type": "markdown", |
335 | | - "metadata": {}, |
| 380 | + "metadata": { |
| 381 | + "jp-MarkdownHeadingCollapsed": true |
| 382 | + }, |
336 | 383 | "source": [ |
337 | 384 | "## 8. On-Demand Data Capture\n", |
338 | 385 | "\n", |
|
373 | 420 | }, |
374 | 421 | { |
375 | 422 | "cell_type": "markdown", |
376 | | - "metadata": {}, |
| 423 | + "metadata": { |
| 424 | + "jp-MarkdownHeadingCollapsed": true |
| 425 | + }, |
377 | 426 | "source": [ |
378 | 427 | "## 9. Droplet Detection (if available)\n", |
379 | 428 | "\n", |
|
411 | 460 | " print(\"❌ Droplet detection not available\")\n" |
412 | 461 | ] |
413 | 462 | }, |
| 463 | + { |
| 464 | + "cell_type": "markdown", |
| 465 | + "metadata": {}, |
| 466 | + "source": [ |
| 467 | + "## 10. Syringe Pump Control (if available)\n", |
| 468 | + "\n", |
| 469 | + "This section uses the lightweight pump client. It supports the WoT pump Thing at `/pump/` and falls back to legacy `/api/control/pump/*` endpoints if present.\n" |
| 470 | + ] |
| 471 | + }, |
| 472 | + { |
| 473 | + "cell_type": "code", |
| 474 | + "execution_count": 5, |
| 475 | + "metadata": {}, |
| 476 | + "outputs": [ |
| 477 | + { |
| 478 | + "name": "stdout", |
| 479 | + "output_type": "stream", |
| 480 | + "text": [ |
| 481 | + "Pump D state: {'pump': 'D', 'flow': 2500.0, 'diameter': 8.17, 'direction': 1, 'state': False, 'unit': 'UL/HR', 'gearbox': '100:1', 'microstep': '1/8', 'threadrod': '1-START', 'enabled': False}\n" |
| 482 | + ] |
| 483 | + } |
| 484 | + ], |
| 485 | + "source": [ |
| 486 | + "from api.client.syringe_pump_api import SyringePumpAPI, PumpAPIError\n", |
| 487 | + "\n", |
| 488 | + "pump_api = SyringePumpAPI(base_url=API_BASE_URL, use_wot=False)\n", |
| 489 | + "\n", |
| 490 | + "try:\n", |
| 491 | + " pump=\"D\"\n", |
| 492 | + " state = pump_api.get_state(pump)\n", |
| 493 | + " print(f\"Pump {pump} state: {state}\")\n", |
| 494 | + " #print(state)\n", |
| 495 | + "\n", |
| 496 | + " # Example commands (uncomment when pump backend is available):\n", |
| 497 | + " # pump_api.set_diameter(pump, 8.17)\n", |
| 498 | + " # pump_api.set_direction(pump, \"infuse\")\n", |
| 499 | + " # pump_api.set_flow(pump, 100.0)\n", |
| 500 | + " # pump_api.set_state(pump, \"run\")\n", |
| 501 | + "except PumpAPIError as e:\n", |
| 502 | + " print(f\"❌ Pump API error: {e}\")\n", |
| 503 | + "except Exception as e:\n", |
| 504 | + " print(f\"❌ Pump not available: {e}\")" |
| 505 | + ] |
| 506 | + }, |
414 | 507 | { |
415 | 508 | "cell_type": "markdown", |
416 | 509 | "metadata": {}, |
|
426 | 519 | } |
427 | 520 | ], |
428 | 521 | "metadata": { |
| 522 | + "kernelspec": { |
| 523 | + "display_name": "Python 3 (ipykernel)", |
| 524 | + "language": "python", |
| 525 | + "name": "python3" |
| 526 | + }, |
429 | 527 | "language_info": { |
430 | | - "name": "python" |
| 528 | + "codemirror_mode": { |
| 529 | + "name": "ipython", |
| 530 | + "version": 3 |
| 531 | + }, |
| 532 | + "file_extension": ".py", |
| 533 | + "mimetype": "text/x-python", |
| 534 | + "name": "python", |
| 535 | + "nbconvert_exporter": "python", |
| 536 | + "pygments_lexer": "ipython3", |
| 537 | + "version": "3.11.4" |
431 | 538 | } |
432 | 539 | }, |
433 | 540 | "nbformat": 4, |
434 | | - "nbformat_minor": 2 |
| 541 | + "nbformat_minor": 4 |
435 | 542 | } |
0 commit comments