### Install pycentauri with optional extras Source: https://context7.com/bjan/pycentauri/llms.txt Install the base library or include optional extras for the HTTP server and/or MCP server. ```bash pip install pycentauri pip install "pycentauri[mcp]" pip install "pycentauri[server]" pip install "pycentauri[mcp,server]" ``` -------------------------------- ### Install pycentauri and optional features Source: https://github.com/bjan/pycentauri/blob/main/README.md Install the core library and CLI, or include optional features like the MCP server or HTTP server. ```sh pip install pycentauri # library + CLI pip install "pycentauri[mcp]" # + MCP server pip install "pycentauri[server]" # + HTTP REST/SSE server + web UI pip install "pycentauri[mcp,server]" # all Python surfaces ``` -------------------------------- ### Start RTSP Bridge Server Source: https://context7.com/bjan/pycentauri/llms.txt Starts the RTSP bridge server with default settings. Requires the --rtsp flag to be enabled. ```bash centauri server --host 192.168.1.209 --rtsp & ``` -------------------------------- ### Set up Development Environment Source: https://github.com/bjan/pycentauri/blob/main/CONTRIBUTING.md Clone the repository, create and activate a virtual environment, and install the project with development dependencies. ```sh git clone https://github.com/bjan/pycentauri cd pycentauri python -m venv .venv . .venv/bin/activate pip install -e ".[mcp,dev]" ``` -------------------------------- ### Programmatic RTSP Bridge Setup Source: https://context7.com/bjan/pycentauri/llms.txt Configures and runs the RTSP bridge programmatically using `RtspConfig`. Handles potential `RtspError` during setup. ```python import asyncio from pycentauri.rtsp import RtspConfig, run, RtspError cfg = RtspConfig( printer_host="192.168.1.209", rtsp_port=8554, bind="0.0.0.0", path="printer", fps=15, bitrate="2M", preset="veryfast", enable_webrtc=False, enable_hls=False, ) try: exit_code = run(cfg) # blocks until Ctrl-C or MediaMTX exits except RtspError as e: print(f"RTSP setup failed: {e}") # e.g.: "MediaMTX is required and was not found on $PATH." ``` -------------------------------- ### Centauri CLI: Starting RTSP Bridge Source: https://context7.com/bjan/pycentauri/llms.txt Run the RTSP bridge standalone using `centauri rtsp`. Configure FPS and bitrate. ```bash centauri rtsp --host 192.168.1.209 --fps 15 --bitrate 4M ``` -------------------------------- ### HTTP Server: Starting a Print Job Source: https://context7.com/bjan/pycentauri/llms.txt Initiate a print job by sending a POST request to `/print/start` with a JSON payload specifying the filename, storage, and auto-leveling preference. ```bash curl -X POST http://localhost:8787/print/start \ -H "Content-Type: application/json" \ -d '{"filename": "benchy.gcode", "storage": "local", "auto_leveling": true}' ``` -------------------------------- ### HTTP Server: Starting Server with Control Enabled Source: https://context7.com/bjan/pycentauri/llms.txt Start the server with control endpoints enabled by adding the `--enable-control` flag. This is necessary for executing print control commands via the API. ```bash centauri server --host 192.168.1.209 --enable-control & ``` -------------------------------- ### Connect and interact with the printer using Python Source: https://github.com/bjan/pycentauri/blob/main/README.md An asynchronous Python example demonstrating connection, status retrieval, snapshot capture, and watching for updates. Control actions require `enable_control=True` during connection. ```python import asyncio from pycentauri import Printer async def main(): async with await Printer.connect("192.168.1.209") as printer: status = await printer.status() print(status.print_status, status.progress, status.temp_nozzle) jpeg = await printer.snapshot() with open("shot.jpg", "wb") as f: f.write(jpeg) async for update in printer.watch(): print(update.print_status, update.progress) asyncio.run(main()) ``` -------------------------------- ### HTTP Server: Getting Service Info Source: https://context7.com/bjan/pycentauri/llms.txt Retrieve health and version information from the server using a GET request to `/api/info`. ```bash curl http://localhost:8787/api/info ``` -------------------------------- ### Centauri CLI: Starting HTTP + SSE Server Source: https://context7.com/bjan/pycentauri/llms.txt Launch the integrated FastAPI server with `centauri server`. Specify host and port. Requires the `pycentauri[server]` extra. ```bash centauri server --host 192.168.1.209 --port 8787 ``` -------------------------------- ### Pycentauri Request Flow: POST /api/rtsp/start Source: https://github.com/bjan/pycentauri/blob/main/docs/ARCHITECTURE.md Details the request flow for starting an RTSP stream. It includes ensuring necessary binaries, rendering configuration, and starting the MediaMTX subprocess. ```text POST /api/rtsp/start │ ▼ RtspController.start() │ ├── ensure_binaries() # mediamtx + ffmpeg ├── _mediamtx_yaml() # render runOnDemand command ├── start_detached() # subprocess.Popen → mediamtx │ ▼ Returns /api/rtsp state JSON (Later, a client connects to rtsp://host:8554/printer → MediaMTX runs the ffmpeg subprocess that pulls printer:3031/video, transcodes to H.264, hands the H.264 bitstream back to MediaMTX, which serves it as RTSP.) ``` -------------------------------- ### HTTP Server: Downloading Snapshot Source: https://context7.com/bjan/pycentauri/llms.txt Download a JPEG snapshot from the printer by making a GET request to `/snapshot` and saving the output to a file. ```bash curl -o snapshot.jpg http://localhost:8787/snapshot ``` -------------------------------- ### Start the HTTP server Source: https://github.com/bjan/pycentauri/blob/main/README.md Launch the HTTP server for REST API access and the web UI. Use `--bind 0.0.0.0` for external access and `--enable-control` for write operations. The `--rtsp` flag enables the RTSP bridge. ```sh # Read-only, bound to loopback so only this box can hit it: centauri server --host 192.168.1.209 --port 8787 # Read + write + RTSP, bound to all interfaces (put a reverse proxy in front): centauri server --host 192.168.1.209 --bind 0.0.0.0 --port 8787 \ --enable-control --rtsp ``` -------------------------------- ### Start a Print Job Source: https://context7.com/bjan/pycentauri/llms.txt Initiate a print job using `Printer.start_print()`. This requires `enable_control=True` during connection. You can specify storage location, auto-leveling, and timelapse settings. Errors like `ControlDisabledError` or `PrinterError` may be raised. ```python import asyncio from pycentauri import Printer, discover from pycentauri.client import ControlDisabledError, PrinterError async def main(): found = await discover(timeout=2.0) mid = found[0].mainboard_id if found else None async with await Printer.connect("192.168.1.209", enable_control=True, mainboard_id=mid) as printer: try: result = await printer.start_print( "benchy.gcode", storage="local", # or "udisk" for USB auto_leveling=True, timelapse=False, ) print("Print started, response:", result.inner) except ControlDisabledError as e: print(f"Control not enabled: {e}") except PrinterError as e: print(f"Printer error: {e}") asyncio.run(main()) ``` -------------------------------- ### Centauri CLI: Running MCP stdio Server Source: https://context7.com/bjan/pycentauri/llms.txt Start the MCP stdio server with `centauri mcp`. Control commands require `--enable-control`. ```bash centauri mcp --host 192.168.1.209 ``` ```bash centauri mcp --host 192.168.1.209 --enable-control ``` -------------------------------- ### HTTP Server: LAN Discovery Source: https://context7.com/bjan/pycentauri/llms.txt Perform a LAN discovery to find printers by sending a GET request to the `/discover` endpoint. ```bash curl http://localhost:8787/discover ``` -------------------------------- ### Get printer status via CLI Source: https://github.com/bjan/pycentauri/blob/main/README.md Retrieve the current status of the printer, either in a human-readable format or as JSON. ```sh centauri status --host 192.168.1.209 centauri status --host 192.168.1.209 --json ``` -------------------------------- ### Pycentauri Request Flow: GET /status Source: https://github.com/bjan/pycentauri/blob/main/docs/ARCHITECTURE.md Illustrates the flow for a GET /status request, from the HTTP client to the Printer.status() method. It highlights how the reader task populates status information. ```text HTTP client │ ▼ FastAPI route ── PrinterManager.printer ──► Printer.status() │ (subscribed already, _latest_status set) │ ▼ Status.from_payload(raw) │ ▼ JSON body ``` -------------------------------- ### Centauri CLI: Controlling Print Jobs Source: https://context7.com/bjan/pycentauri/llms.txt Manage print jobs (start, pause, resume, stop) using the `centauri print` command. Requires `--enable-control`. Options like `--no-auto-level` and `--timelapse` are available for starting prints. ```bash centauri print start benchy.gcode --host 192.168.1.209 --enable-control ``` ```bash centauri print start benchy.gcode --host 192.168.1.209 --enable-control --no-auto-level --timelapse ``` ```bash centauri print pause --host 192.168.1.209 --enable-control ``` ```bash centauri print resume --host 192.168.1.209 --enable-control ``` ```bash centauri print stop --host 192.168.1.209 --enable-control ``` -------------------------------- ### Get printer attributes via CLI Source: https://github.com/bjan/pycentauri/blob/main/README.md Retrieve printer attributes such as model, firmware, and capabilities using the `centauri attributes` command. ```sh centauri attributes --host 192.168.1.209 ``` -------------------------------- ### Control printer actions via CLI Source: https://github.com/bjan/pycentauri/blob/main/README.md Start, pause, resume, or stop print jobs using CLI commands. Requires `--enable-control`. ```sh centauri print start cube.gcode --host 192.168.1.209 --enable-control centauri print pause --host 192.168.1.209 --enable-control centauri print resume --host 192.168.1.209 --enable-control centauri print stop --host 192.168.1.209 --enable-control ``` -------------------------------- ### Run Centauri in Standalone RTSP Mode Source: https://github.com/bjan/pycentauri/blob/main/README.md Starts the Centauri service in standalone mode to stream RTSP. Useful for direct integration with media players or NVR systems. Ctrl-C stops the process. ```bash centauri rtsp --host 192.168.1.209 ``` -------------------------------- ### Status Payload - Older Schema Source: https://github.com/bjan/pycentauri/blob/main/docs/PROTOCOL.md Example of the status payload structure for older firmware versions, as documented in CentauriLink. This schema uses pair-form temperatures. ```jsonc // Older (CentauriLink-documented — pair-form temps): { "TempOfNozzle": [target, actual], ... } ``` -------------------------------- ### Open WebSocket connection to printer Source: https://context7.com/bjan/pycentauri/llms.txt Opens a WebSocket connection to the printer and starts the reader task. Pass enable_control=True to unlock write actions. Pass mainboard_id= to skip waiting for Attributes push, which is required when the printer is paused or in an error state. ```python import asyncio from pycentauri import Printer, discover async def main(): # Pre-discover to get the mainboard ID (required in paused/error states) found = await discover(timeout=2.0) mid = found[0].mainboard_id if found else None # Read-only connection (default) async with await Printer.connect("192.168.1.209", mainboard_id=mid) as printer: status = await printer.status() print(status.print_status, status.progress) # With control enabled async with await Printer.connect("192.168.1.209", enable_control=True, mainboard_id=mid) as printer: await printer.start_print("cube.gcode") asyncio.run(main()) ``` -------------------------------- ### Register Centauri with Claude Code MCP with Control Actions Source: https://github.com/bjan/pycentauri/blob/main/README.md Registers the Pycentauri server with Claude Code's MCP, enabling control actions like start, pause, resume, and stop. This is achieved by adding the --enable-control flag. ```bash claude mcp add pycentauri --env PYCENTAURI_HOST=192.168.1.209 \ -- python -m pycentauri.mcp --enable-control ``` -------------------------------- ### Status Payload - V1.1.x Schema Source: https://github.com/bjan/pycentauri/blob/main/docs/PROTOCOL.md Example of the status payload structure for firmware version V1.1.x. This schema includes scalar temperatures and separate target keys. Note the firmware typos 'CurrenStatus' and 'CurrenCoord'. ```jsonc // V1.1.x (current — scalar temps, separate target keys): { "CurrentStatus": [1], "TimeLapseStatus": 0, "PlatFormType": 0, "TempOfHotbed": 50.04, "TempOfNozzle": 255.01, "TempOfBox": 29.20, "TempTargetHotbed": 50, "TempTargetNozzle": 255, "TempTargetBox": 0, "CurrenCoord": "139.96,123.71,5.33", "CurrentFanSpeed": { "ModelFan": 58, "AuxiliaryFan": 0, "BoxFan": 68 }, "ZOffset": 0.415, "LightStatus": { "SecondLight": 1, "RgbLight": [0,0,0] }, "PrintInfo": { "Status": 13, "CurrentLayer": 34, "TotalLayer": 438, "CurrentTicks": 364.98, "TotalTicks": 4504, "Filename": "ECC_0.4_temperature_tower_PLA0.16_1h15m.gcode", "TaskId": "295cb186-daf5-4b84-9668-59a520e4640a", "PrintSpeedPct": 100, "Progress": 9 } } ``` -------------------------------- ### HTTP Server: Getting Printer Attributes Source: https://context7.com/bjan/pycentauri/llms.txt Retrieve printer attributes by sending a GET request to the `/attributes` endpoint. ```bash curl http://localhost:8787/attributes ``` -------------------------------- ### HTTP Server: Getting Cached Status Source: https://context7.com/bjan/pycentauri/llms.txt Fetch the last known printer status from the server's cache by making a GET request to `/status`. ```bash curl http://localhost:8787/status ``` -------------------------------- ### Relaunch App Daemon via SSH Source: https://github.com/bjan/pycentauri/blob/main/docs/PROTOCOL.md Use this command to relaunch the 'app' daemon if it has crashed. Ensure you have SSH access to the printer. ```bash ssh printer "setsid nohup /app/app /tmp/app.log 2>&1 &" ``` -------------------------------- ### Printer.start_print() Source: https://context7.com/bjan/pycentauri/llms.txt Initiates a print job for a specified file. This method requires `enable_control=True` and can take optional arguments for storage location, auto-leveling, and timelapse. It returns a `ParsedMessage` on success or raises `ControlDisabledError` or `PrinterError` on failure. ```APIDOC ## `Printer.start_print()` — start a print job Sends a `START_PRINT` SDCP command to begin printing a file that already resides on the printer's internal storage or USB drive. Requires `enable_control=True`. Optional arguments: `storage` (`"local"` or `"udisk"`), `auto_leveling` (default `True`), `timelapse` (default `False`). Raises `ControlDisabledError` if `enable_control` is not set. ```python import asyncio from pycentauri import Printer, discover from pycentauri.client import ControlDisabledError, PrinterError async def main(): found = await discover(timeout=2.0) mid = found[0].mainboard_id if found else None async with await Printer.connect("192.168.1.209", enable_control=True, mainboard_id=mid) as printer: try: result = await printer.start_print( "benchy.gcode", storage="local", # or "udisk" for USB auto_leveling=True, timelapse=False, ) print("Print started, response:", result.inner) except ControlDisabledError as e: print(f"Control not enabled: {e}") except PrinterError as e: print(f"Printer error: {e}") asyncio.run(main()) ``` ``` -------------------------------- ### Control RTSP Bridge Source: https://context7.com/bjan/pycentauri/llms.txt Commands to start or stop the RTSP bridge service. These are typically used for managing the streaming service. ```bash curl -X POST http://localhost:8787/api/rtsp/start ``` ```bash curl -X POST http://localhost:8787/api/rtsp/stop ``` -------------------------------- ### Untested but documented in the SDK Source: https://github.com/bjan/pycentauri/blob/main/docs/PROTOCOL.md These commands are documented in the SDK but have not been tested by pycentauri. They may or may not work. ```APIDOC ## MOVE_AXES ### Description Moves the printer axes. ### Method `POST` ### Endpoint `/move/axes` ### Parameters #### Request Body - **Axis** (string) - Required - The axis to move (X, Y, or Z). - **Step** (float) - Required - The distance to move in millimeters. ### Request Example ```json { "Axis": "X", "Step": 10.5 } ``` ``` ```APIDOC ## HOME_AXES ### Description Homes the specified printer axes. ### Method `POST` ### Endpoint `/home/axes` ### Parameters #### Request Body - **Axis** (string) - Required - The axes to home (X, Y, Z, XY, or XYZ). ### Request Example ```json { "Axis": "XYZ" } ``` ``` ```APIDOC ## SET_TEMPERATURE ### Description Sets the target temperatures for the nozzle, hotbed, and box. ### Method `POST` ### Endpoint `/set/temperature` ### Parameters #### Request Body - **TempTargetNozzle** (integer) - Optional - Target temperature for the nozzle in °C. - **TempTargetHotbed** (integer) - Optional - Target temperature for the hotbed in °C. - **TempTargetBox** (integer) - Optional - Target temperature for the box in °C. ### Request Example ```json { "TempTargetNozzle": 210, "TempTargetHotbed": 60 } ``` ``` ```APIDOC ## SET_FAN_SPEED ### Description Sets the speed for the printer's fans. ### Method `POST` ### Endpoint `/set/fan_speed` ### Parameters #### Request Body - **TargetFanSpeed** (object) - Required - Fan speed settings. - **ModelFan** (integer) - Optional - Speed of the model fan (0-100). - **BoxFan** (integer) - Optional - Speed of the box fan (0-100). - **AuxiliaryFan** (integer) - Optional - Speed of the auxiliary fan (0-100). ### Request Example ```json { "TargetFanSpeed": { "ModelFan": 80, "BoxFan": 50 } } ``` ``` ```APIDOC ## SET_PRINT_SPEED ### Description Sets the print speed percentage. ### Method `POST` ### Endpoint `/set/print_speed` ### Parameters #### Request Body - **PrintSpeedPct** (integer) - Required - The print speed percentage (0-100). ### Request Example ```json { "PrintSpeedPct": 75 } ``` ``` ```APIDOC ## SET_LIGHT ### Description Controls the printer's light settings. ### Method `POST` ### Endpoint `/set/light` ### Parameters #### Request Body - **brightness** (object) - Required - Light brightness payload. Specific structure depends on implementation. ### Request Example ```json { "brightness": { ... } } ``` ``` ```APIDOC ## VIDEO_STREAM ### Description Controls the video stream. ### Method `POST` ### Endpoint `/video/stream` ### Parameters #### Request Body - **control_payload** (object) - Required - Payload for controlling the video stream. ### Request Example ```json { "control_payload": { ... } } ``` ``` ```APIDOC ## LOAD_FILAMENT ### Description Initiates the filament loading process. ### Method `POST` ### Endpoint `/filament/load` ### Parameters #### Request Body (TBD) - Payload details are not yet defined. ### Request Example ```json { ... } ``` ``` ```APIDOC ## UNLOAD_FILAMENT ### Description Initiates the filament unloading process. ### Method `POST` ### Endpoint `/filament/unload` ### Parameters #### Request Body (TBD) - Payload details are not yet defined. ### Request Example ```json { ... } ``` ``` ```APIDOC ## SET_PRINTER_NAME ### Description Sets the name of the printer. ### Method `POST` ### Endpoint `/set/printer_name` ### Parameters #### Request Body - **Name** (string) - Required - The new name for the printer. ### Request Example ```json { "Name": "MyPrinter" } ``` ``` -------------------------------- ### Run Integration Tests Source: https://github.com/bjan/pycentauri/blob/main/CONTRIBUTING.md Execute integration tests against a real Elegoo Centauri Carbon printer on your local network. Ensure the PYCENTAURI_TEST_HOST environment variable is set to the printer's IP address. ```sh PYCENTAURI_TEST_HOST=192.168.1.x pytest tests/integration ``` -------------------------------- ### Create FastAPI App with Pycentauri Source: https://context7.com/bjan/pycentauri/llms.txt Programmatically create a FastAPI application instance with Pycentauri integration. Supports read-only mode or full control with RTSP. ```python import uvicorn from pycentauri.server import create_app from pycentauri.rtsp import RtspConfig # Read-only server (default) app = create_app("192.168.1.209") # With control and RTSP bridge rtsp_cfg = RtspConfig( printer_host="192.168.1.209", rtsp_port=8554, fps=15, bitrate="2M", preset="veryfast", ) app = create_app( "192.168.1.209", enable_control=True, mainboard_id="ABC123DEF456", # pre-seed from discovery rtsp_config=rtsp_cfg, ) # Run directly uvicorn.run(app, host="0.0.0.0", port=8787) # Or mount as a sub-application in an existing FastAPI app from fastapi import FastAPI root = FastAPI() root.mount("/printer", app) ``` -------------------------------- ### CLI Commands Source: https://github.com/bjan/pycentauri/blob/main/README.md Command-line interface for interacting with the Elegoo Centauri printer. ```APIDOC ## CLI Commands ### discover Find printers on your LAN. ### status Get one-shot status of the printer (pretty or JSON). - `--json`: Output status in JSON format. ### watch Stream live status updates from the printer. ### snapshot Grab a webcam snapshot from the printer. - `shot.jpg`: The filename to save the snapshot to. ### attributes Retrieve printer attributes (model, firmware, mainboard ID, capabilities). ### print start Start printing a G-code file. - `cube.gcode`: The G-code file to print. - `--enable-control`: Required to enable control actions. ### print pause Pause the current print job. - `--enable-control`: Required to enable control actions. ### print resume Resume a paused print job. - `--enable-control`: Required to enable control actions. ### print stop Stop the current print job. - `--enable-control`: Required to enable control actions. **Note:** The host can be specified using `--host` or the `PYCENTAURI_HOST` environment variable. If not set, commands will attempt auto-discovery. ``` -------------------------------- ### Untested Documented Commands Source: https://github.com/bjan/pycentauri/blob/main/docs/PROTOCOL.md Commands documented in the SDK but not yet tested with PyCentauri. These may or may not work on CC firmware. Cmd 403 is overloaded and may work across all its variants if it functions at all. ```text Cmd | Name | Payload sketch --- 401 | `MOVE_AXES` | `{"Axis": "X\|Y\|Z", "Step": }` 402 | `HOME_AXES` | `{"Axis": "X\|Y\|Z\|XY\|XYZ"}` 403 | `SET_TEMPERATURE` | `{"TempTargetNozzle": <°C>, "TempTargetHotbed": <°C>, "TempTargetBox": <°C>}` 403 | `SET_FAN_SPEED` | `{"TargetFanSpeed": {"ModelFan": <0-100>, "BoxFan": <0-100>, "AuxiliaryFan": <0-100>}}` 403 | `SET_PRINT_SPEED` | `{"PrintSpeedPct": }` 403 | `SET_LIGHT` | (brightness payload) 386 | `VIDEO_STREAM` | (control payload) 1024 | `LOAD_FILAMENT` | (TBD) 1025 | `UNLOAD_FILAMENT` | (TBD) 1043 | `SET_PRINTER_NAME` | `{"Name": ""}` ``` -------------------------------- ### Centauri CLI: Taking Webcam Snapshots Source: https://context7.com/bjan/pycentauri/llms.txt Capture a snapshot from the printer's webcam using `centauri snapshot`. Save the image to a file or pipe it to another command like `display`. ```bash centauri snapshot shot.jpg --host 192.168.1.209 ``` ```bash centauri snapshot - --host 192.168.1.209 | display ``` -------------------------------- ### Printer.connect() — open a WebSocket connection Source: https://context7.com/bjan/pycentauri/llms.txt Opens a WebSocket connection to the printer and returns a Printer instance. Control actions can be enabled by passing `enable_control=True`. The `mainboard_id` can be provided to skip waiting for firmware attributes, which is useful when the printer is paused or in an error state. ```APIDOC ## Printer.connect() ### Description Class method that opens a WebSocket to `ws://:3030/websocket` and starts the reader task. Returns a `Printer` instance ready to use. Pass `enable_control=True` to unlock write actions. Pass `mainboard_id=` (from a prior `discover()`) to skip waiting for the firmware's `Attributes` push — required when the printer is paused or in an error state. ### Parameters #### Path Parameters - **host** (string) - Required - The hostname or IP address of the printer. #### Query Parameters - **enable_control** (boolean) - Optional - If True, enables write actions (control commands). - **mainboard_id** (string) - Optional - The mainboard ID obtained from a prior `discover()` call. Used to skip waiting for firmware attributes. ### Request Example ```python import asyncio from pycentauri import Printer, discover async def main(): # Pre-discover to get the mainboard ID (required in paused/error states) found = await discover(timeout=2.0) mid = found[0].mainboard_id if found else None # Read-only connection (default) async with await Printer.connect("192.168.1.209", mainboard_id=mid) as printer: status = await printer.status() print(status.print_status, status.progress) # With control enabled async with await Printer.connect("192.168.1.209", enable_control=True, mainboard_id=mid) as printer: await printer.start_print("cube.gcode") asyncio.run(main()) ``` ``` -------------------------------- ### Get Printer Attributes Source: https://context7.com/bjan/pycentauri/llms.txt Retrieve printer hardware and firmware details using `Printer.attributes()`. This method caches results, so subsequent calls are faster. Ensure the printer is connected before calling. ```python import asyncio from pycentauri import Printer async def main(): async with await Printer.connect("192.168.1.209") as printer: attrs = await printer.attributes() print(f"Mainboard ID: {attrs.mainboard_id}") # ABC123DEF456 print(f"Name: {attrs.name}") # Centauri Carbon print(f"Machine name: {attrs.machine_name}") # CentauriCarbon print(f"Firmware: {attrs.firmware_version}") # V1.1.46 print(f"Protocol: {attrs.protocol_version}") # 3.0.0 print(f"Capabilities: {attrs.capabilities}") # ['print', 'camera'] asyncio.run(main()) ``` -------------------------------- ### Confirmed-Working Commands Source: https://github.com/bjan/pycentauri/blob/main/docs/PROTOCOL.md List of SDCP commands that have been confirmed to work with PyCentauri. These commands cover basic printer status, print control, and subscription services. ```text Cmd | Name | Payload | Returns --- 0 | `GET_PRINTER_STATUS` | `{}` | `Ack=0` (the real status arrives separately on the status topic) 1 | `GET_PRINTER_ATTRIBUTES`| `{}` | `Ack=0` (attributes arrive on attributes topic) 128 | `START_PRINT` | `{Filename, StartLayer, Calibration_switch, PrintPlatformType, Tlp_Switch, slot_map}` | `Ack=0` 129 | `PAUSE_PRINT` | `{}` | `Ack=0` 130 | `STOP_PRINT` | `{}` | `Ack=0` 131 | `RESUME_PRINT` | `{}` | `Ack=0` 324 | `GET_CANVAS_STATUS` | `{}` | enabled in SDK; not yet exercised by pycentauri 512 | `SUBSCRIBE` | `{"TimePeriod": }` | `Ack=0`, then status pushes ``` -------------------------------- ### Confirmed-working Commands Source: https://github.com/bjan/pycentauri/blob/main/docs/PROTOCOL.md These commands have been tested and confirmed to work with the printer firmware. ```APIDOC ## GET_PRINTER_STATUS ### Description Retrieves the current status of the printer. ### Method `GET` ### Endpoint `/printer/status` ### Parameters #### Query Parameters None #### Request Body `{}` ### Response #### Success Response (200) `Ack=0` (The real status arrives separately on the status topic) ### Request Example ```json {} ``` ### Response Example ```json { "Ack": 0 } ``` ``` ```APIDOC ## GET_PRINTER_ATTRIBUTES ### Description Retrieves the attributes of the printer. ### Method `GET` ### Endpoint `/printer/attributes` ### Parameters #### Query Parameters None #### Request Body `{}` ### Response #### Success Response (200) `Ack=0` (Attributes arrive on the attributes topic) ### Request Example ```json {} ``` ### Response Example ```json { "Ack": 0 } ``` ``` ```APIDOC ## START_PRINT ### Description Initiates a print job. ### Method `POST` ### Endpoint `/print/start` ### Parameters #### Request Body - **Filename** (string) - Required - The name of the file to print. - **StartLayer** (integer) - Required - The layer to start printing from. - **Calibration_switch** (boolean) - Required - Whether to perform calibration. - **PrintPlatformType** (integer) - Required - The type of print platform. - **Tlp_Switch** (boolean) - Required - Whether to enable TLP. - **slot_map** (object) - Required - Mapping of slots. ### Request Example ```json { "Filename": "example.gcode", "StartLayer": 0, "Calibration_switch": true, "PrintPlatformType": 1, "Tlp_Switch": false, "slot_map": {} } ``` ### Response #### Success Response (200) `Ack=0` ``` ```APIDOC ## PAUSE_PRINT ### Description Pauses the current print job. ### Method `POST` ### Endpoint `/print/pause` ### Parameters #### Request Body `{}` ### Response #### Success Response (200) `Ack=0` ### Request Example ```json {} ``` ``` ```APIDOC ## STOP_PRINT ### Description Stops the current print job. ### Method `POST` ### Endpoint `/print/stop` ### Parameters #### Request Body `{}` ### Response #### Success Response (200) `Ack=0` ### Request Example ```json {} ``` ``` ```APIDOC ## RESUME_PRINT ### Description Resumes a paused print job. ### Method `POST` ### Endpoint `/print/resume` ### Parameters #### Request Body `{}` ### Response #### Success Response (200) `Ack=0` ### Request Example ```json {} ``` ``` ```APIDOC ## GET_CANVAS_STATUS ### Description Retrieves the canvas status. This feature is enabled in the SDK but not yet exercised by pycentauri. ### Method `GET` ### Endpoint `/canvas/status` ### Parameters #### Query Parameters None #### Request Body `{}` ### Response #### Success Response (200) `Ack=0` ### Request Example ```json {} ``` ``` ```APIDOC ## SUBSCRIBE ### Description Subscribes to status updates from the printer. ### Method `POST` ### Endpoint `/subscribe` ### Parameters #### Request Body - **TimePeriod** (integer) - Required - The time period in milliseconds for status updates. ### Request Example ```json { "TimePeriod": 1000 } ``` ### Response #### Success Response (200) `Ack=0`, followed by status pushes. ### Response Example ```json { "Ack": 0 } ``` ``` -------------------------------- ### Subscribe to Status Pushes (Cmd 512) Source: https://github.com/bjan/pycentauri/blob/main/docs/PROTOCOL.md Send Cmd 512 with a TimePeriod in milliseconds to subscribe to real-time status updates from the printer. ```json {"TimePeriod": } ``` -------------------------------- ### Interpreting Print Status Codes in Python Source: https://context7.com/bjan/pycentauri/llms.txt Use PrintStatus constants to interpret the printer's current state. This example shows how to check for common states like printing, paused, completed, or idle. ```python import asyncio from pycentauri import Printer from pycentauri.models import PrintStatus async def main(): async with await Printer.connect("192.168.1.209") as printer: st = await printer.status() code = st.print_status if code == PrintStatus.PRINTING: # 13 print(f"Printing — {st.progress}% done, layer {st.print_info.current_layer}/{st.print_info.total_layer}") elif code == PrintStatus.PAUSED: # 6 print("Print is paused") elif code == PrintStatus.COMPLETED: # 9 print("Print completed!") elif code == PrintStatus.ERROR: # 14 print(f"Printer error! ErrNum={st.print_info.err_num if st.print_info else '?'}") elif code == PrintStatus.AUTO_LEVELING: # 15 print("Auto-leveling in progress") elif code == PrintStatus.PREHEATING: # 16 print("Preheating nozzle/bed") elif code is None or code == PrintStatus.IDLE: # 0 print("Printer is idle") else: print(f"State code: {code}") asyncio.run(main()) ``` -------------------------------- ### Register Pycentauri MCP Server with Claude Source: https://context7.com/bjan/pycentauri/llms.txt Registers the Pycentauri MCP server with Claude, enabling AI agent integration. Supports read-only or control modes. ```bash # Register with Claude Code (read-only) claude mcp add pycentauri \ --env PYCENTAURI_HOST=192.168.1.209 \ -- python -m pycentauri.mcp # Register with control actions enabled claude mcp add pycentauri \ --env PYCENTAURI_HOST=192.168.1.209 \ -- python -m pycentauri.mcp --enable-control ``` ```json # Register with Claude Desktop (add to claude_desktop_config.json): # { # "mcpServers": { # "pycentauri": { # "command": "python", # "args": ["-m", "pycentauri.mcp", "--enable-control"], # "env": { "PYCENTAURI_HOST": "192.168.1.209" } # } # } # } ``` -------------------------------- ### Programmatic MCP Server Construction Source: https://context7.com/bjan/pycentauri/llms.txt Builds and runs an MCP server programmatically, useful for embedding within custom AI agents. Supports control actions. ```python # Programmatic MCP server construction (for embedding in custom agents) from pycentauri.mcp.server import build_server, run_stdio # Build a read-only server mcp = build_server(enable_control=False) # Build a server with control tools mcp = build_server(enable_control=True) # Available tools: # - get_status() → dict with state, progress, temps, fans, raw # - get_attributes() → dict with mainboard_id, firmware, capabilities # - get_snapshot() → MCP Image (JPEG, visible to the LLM) # - discover_printers() → list of dicts with host, mainboard_id, firmware # (with --enable-control:) # - start_print(filename, storage, auto_leveling, timelapse) # - pause_print() # - resume_print() # - stop_print() # Run over stdio (blocks) run_stdio(enable_control=True) ``` -------------------------------- ### Capture webcam snapshot via CLI Source: https://github.com/bjan/pycentauri/blob/main/README.md Save a JPEG snapshot from the printer's webcam to a file using the `centauri snapshot` command. ```sh centauri snapshot --host 192.168.1.209 shot.jpg ``` -------------------------------- ### Get current printer status Source: https://context7.com/bjan/pycentauri/llms.txt Returns a Status object with a normalized view of the SDCP status push. If a push has already been received, it's returned from cache; otherwise, the client subscribes and waits. All temperatures are in °C; .raw holds the original SDCP dict. ```python import asyncio from pycentauri import Printer async def main(): async with await Printer.connect("192.168.1.209") as printer: st = await printer.status() print(f"State: {st.state} (PrintInfo.Status={st.print_status})") print(f"Progress: {st.progress}% File: {st.filename}") print(f"Nozzle: {st.temp_nozzle:.1f}°C / {st.temp_nozzle_target:.0f}°C target") print(f"Bed: {st.temp_bed:.1f}°C / {st.temp_bed_target:.0f}°C target") print(f"Chamber: {st.temp_chamber:.1f}°C") if st.coord: x, y, z = st.coord print(f"Position: X={x:.2f} Y={y:.2f} Z={z:.2f} Z-offset={st.z_offset:.3f}") print(f"Fans: {st.fan_speed}") # {'part': 80, 'aux': 60} # Current layer info (from PrintInfo sub-model) if st.print_info: print(f"Layer: {st.print_info.current_layer}/{st.print_info.total_layer}") asyncio.run(main()) ``` -------------------------------- ### MCP Server - AI Agent Integration Source: https://context7.com/bjan/pycentauri/llms.txt Provides a FastMCP stdio server for integrating with AI agents, with optional control tools. ```bash # Register with Claude Code (read-only) claude mcp add pycentauri \ --env PYCENTAURI_HOST=192.168.1.209 \ -- python -m pycentauri.mcp # Register with control actions enabled claude mcp add pycentauri \ --env PYCENTAURI_HOST=192.168.1.209 \ -- python -m pycentauri.mcp --enable-control # Register with Claude Desktop (add to claude_desktop_config.json): # { # "mcpServers": { # "pycentauri": { # "command": "python", # "args": ["-m", "pycentauri.mcp", "--enable-control"], # "env": { "PYCENTAURI_HOST": "192.168.1.209" } # } # } # } ``` ```python # Programmatic MCP server construction (for embedding in custom agents) from pycentauri.mcp.server import build_server, run_stdio # Build a read-only server mcp = build_server(enable_control=False) # Build a server with control tools mcp = build_server(enable_control=True) # Available tools: # - get_status() → dict with state, progress, temps, fans, raw # - get_attributes() → dict with mainboard_id, firmware, capabilities # - get_snapshot() → MCP Image (JPEG, visible to the LLM) # - discover_printers() → list of dicts with host, mainboard_id, firmware # (with --enable-control:) # - start_print(filename, storage, auto_leveling, timelapse) # - pause_print() # - resume_print() # - stop_print() # Run over stdio (blocks) # run_stdio(enable_control=True) ``` -------------------------------- ### Printer.status() — get current printer status Source: https://context7.com/bjan/pycentauri/llms.txt Retrieves the current status of the printer. If a status update has already been received, it's returned from cache; otherwise, the client subscribes to status updates and waits. Returns a `Status` object with normalized printer information. ```APIDOC ## Printer.status() ### Description Returns a `Status` object with a normalised view of the SDCP status push. If a push has already been received since connecting, it is returned immediately from the in-memory cache; otherwise the client subscribes (Cmd 512) and waits. All temperatures are in °C; `.raw` holds the original SDCP dict for forward-compatibility. ### Parameters This method does not take any parameters. ### Response - **Status** (object) - An object containing the printer's current status, including state, progress, temperatures, coordinates, fan speed, and print information. - **state** (string) - The current state of the printer. - **print_status** (string) - The status of the current print job. - **progress** (float) - The percentage of the print job completed. - **filename** (string) - The name of the currently printing file. - **temp_nozzle** (float) - The current nozzle temperature in °C. - **temp_nozzle_target** (float) - The target nozzle temperature in °C. - **temp_bed** (float) - The current bed temperature in °C. - **temp_bed_target** (float) - The target bed temperature in °C. - **temp_chamber** (float) - The current chamber temperature in °C. - **coord** (tuple) - The current X, Y, Z coordinates of the print head. - **z_offset** (float) - The current Z-offset value. - **fan_speed** (dict) - A dictionary representing the fan speeds (e.g., {'part': 80, 'aux': 60}). - **print_info** (object) - An object containing detailed print information, such as current and total layers. - **current_layer** (int) - The current layer number. - **total_layer** (int) - The total number of layers in the print job. - **raw** (dict) - The original SDCP dictionary for forward-compatibility. ### Request Example ```python import asyncio from pycentauri import Printer async def main(): async with await Printer.connect("192.168.1.209") as printer: st = await printer.status() print(f"State: {st.state} (PrintInfo.Status={st.print_status})") print(f"Progress: {st.progress}% File: {st.filename}") print(f"Nozzle: {st.temp_nozzle:.1f}°C / {st.temp_nozzle_target:.0f}°C target") print(f"Bed: {st.temp_bed:.1f}°C / {st.temp_bed_target:.0f}°C target") print(f"Chamber: {st.temp_chamber:.1f}°C") if st.coord: x, y, z = st.coord print(f"Position: X={x:.2f} Y={y:.2f} Z={z:.2f} Z-offset={st.z_offset:.3f}") print(f"Fans: {st.fan_speed}") # Current layer info (from PrintInfo sub-model) if st.print_info: print(f"Layer: {st.print_info.current_layer}/{st.print_info.total_layer}") asyncio.run(main()) ``` ### Response Example ``` State: Printing (PrintInfo.Status=Printing) Progress: 50.0% File: cube.gcode Nozzle: 210.5°C / 210°C target Bed: 60.1°C / 60°C target Chamber: 35.0°C Position: X=100.00 Y=50.00 Z=10.00 Z-offset=0.000 Fans: {'part': 80, 'aux': 60} Layer: 100/200 ``` ```