-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Attempt too support both API versions
- Loading branch information
Showing
6 changed files
with
282 additions
and
146 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
class PrusaLinkError(Exception): | ||
"""Base class for PrusaLink errors.""" | ||
|
||
|
||
class InvalidAuth(PrusaLinkError): | ||
"""Error to indicate there is invalid auth.""" | ||
|
||
|
||
class Conflict(PrusaLinkError): | ||
"""Error to indicate the command hit a conflict.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,131 +1,42 @@ | ||
from enum import Enum | ||
from typing import TypedDict | ||
|
||
"""Types of the v1 API. Source: https://github.com/prusa3d/Prusa-Link-Web/blob/master/spec/openapi.yaml""" | ||
|
||
|
||
class PrusaLinkError(Exception): | ||
"""Base class for PrusaLink errors.""" | ||
|
||
|
||
class InvalidAuth(PrusaLinkError): | ||
"""Error to indicate there is invalid auth.""" | ||
|
||
|
||
class Conflict(PrusaLinkError): | ||
"""Error to indicate the command hit a conflict.""" | ||
|
||
|
||
class Capabilities(TypedDict): | ||
"""API Capabilities""" | ||
|
||
upload_by_put: bool | None | ||
"""Types of the non-versioned API. Source: https://github.com/prusa3d/Prusa-Firmware-Buddy/blob/v4.4.1/lib/WUI/link_content/basic_gets.cpp""" | ||
|
||
|
||
class VersionInfo(TypedDict): | ||
"""Version data.""" | ||
|
||
api: str | ||
version: str | ||
printer: str | ||
server: str | ||
text: str | ||
firmware: str | ||
sdk: str | None | ||
capabilities: Capabilities | None | ||
hostname: str | ||
|
||
|
||
class PrinterInfo(TypedDict): | ||
"""Printer informations.""" | ||
|
||
mmu: bool | None | ||
name: str | None | ||
location: str | None | ||
farm_mode: bool | None | ||
nozzle_diameter: float | None | ||
min_extrusion_temp: int | None | ||
serial: str | None | ||
sd_ready: bool | None | ||
active_camera: bool | None | ||
hostname: str | None | ||
port: str | None | ||
network_error_chime: bool | None | ||
|
||
|
||
class StatusInfo(TypedDict): | ||
"""Status of the printer.""" | ||
|
||
ok: bool | None | ||
message: str | None | ||
"""Printer data.""" | ||
|
||
telemetry: dict | ||
temperature: dict | ||
state: dict | ||
|
||
class PrinterState(Enum): | ||
"""Printer state as Enum.""" | ||
|
||
IDLE = "IDLE" | ||
BUSY = "BUSY" | ||
PRINTING = "PRINTING" | ||
PAUSED = "PAUSED" | ||
FINISHED = "FINISHED" | ||
STOPPED = "STOPPED" | ||
ERROR = "ERROR" | ||
ATTENTION = "ATTENTION" | ||
READY = "READY" | ||
|
||
|
||
class PrinterStatusInfo(TypedDict): | ||
"""Printer information.""" | ||
|
||
state: PrinterState | ||
temp_nozzle: float | None | ||
target_nozzle: float | None | ||
temp_bed: float | None | ||
target_bed: float | None | ||
axis_x: float | None | ||
axis_y: float | None | ||
axis_z: float | None | ||
flow: int | None | ||
speed: int | None | ||
fan_hotend: int | None | ||
fan_print: int | None | ||
status_printer: StatusInfo | None | ||
status_connect: StatusInfo | None | ||
|
||
|
||
class PrinterStatus(TypedDict): | ||
"""Printer status.""" | ||
|
||
printer: PrinterStatusInfo | ||
|
||
|
||
class PrintFileRefs(TypedDict): | ||
"""Additional Files for the current Job""" | ||
class JobInfo(TypedDict): | ||
"""Job data.""" | ||
|
||
download: str | None | ||
icon: str | None | ||
thumbnail: str | None | ||
state: str | ||
job: dict | None | ||
|
||
|
||
class JobFilePrint(TypedDict): | ||
"""Currently printed file informations.""" | ||
class FileInfo(TypedDict): | ||
"""File data.""" | ||
|
||
name: str | ||
display_name: str | None | ||
path: str | ||
display_path: str | None | ||
size: int | None | ||
m_timestamp: int | ||
meta: dict | None | ||
refs: PrintFileRefs | None | ||
origin: str | ||
size: int | ||
refs: dict | ||
|
||
|
||
class JobInfo(TypedDict): | ||
"""Job information.""" | ||
class FilesInfo(TypedDict): | ||
"""Files data.""" | ||
|
||
id: int | ||
state: str | ||
progress: int | ||
time_remaining: int | None | ||
time_printing: int | ||
inaccurate_estimates: bool | None | ||
serial_print: bool | None | ||
file: JobFilePrint | None | ||
files: list[FileInfo] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
"""Prusalink API.""" | ||
from __future__ import annotations | ||
|
||
from aiohttp import ClientSession | ||
from pyprusalink.client import ApiClient | ||
from pyprusalink.types_legacy import LegacyPrinterStatus | ||
from pyprusalink.v1.types import JobInfo, PrinterInfo, PrinterStatus, VersionInfo | ||
|
||
|
||
class PrusaLink: | ||
"""Wrapper for the Prusalink API. | ||
Data format can be found here: | ||
https://github.com/prusa3d/Prusa-Link-Web/blob/master/spec/openapi.yaml | ||
""" | ||
|
||
def __init__( | ||
self, session: ClientSession, host: str, username: str, password: str | ||
) -> None: | ||
"""Initialize the PrusaLink class.""" | ||
self.client = ApiClient.get_http_digest_client( | ||
session=session, host=host, username=username, password=password | ||
) | ||
|
||
async def cancel_job(self, jobId: int) -> None: | ||
"""Cancel the current job.""" | ||
async with self.client.request("DELETE", f"/api/v1/job/{jobId}"): | ||
pass | ||
|
||
async def pause_job(self, jobId: int) -> None: | ||
"""Pause a job.""" | ||
async with self.client.request("PUT", f"/api/v1/job/{jobId}/pause"): | ||
pass | ||
|
||
async def resume_job(self, jobId: int) -> None: | ||
"""Resume a paused job.""" | ||
async with self.client.request("PUT", f"/api/v1/job/{jobId}/resume"): | ||
pass | ||
|
||
async def get_version(self) -> VersionInfo: | ||
"""Get the version.""" | ||
async with self.client.request("GET", "/api/version") as response: | ||
return await response.json() | ||
|
||
async def get_legacy_printer(self) -> LegacyPrinterStatus: | ||
"""Get the legacy printer endpoint.""" | ||
async with self.client.request("GET", "/api/printer") as response: | ||
return await response.json() | ||
|
||
async def get_info(self) -> PrinterInfo: | ||
"""Get the printer.""" | ||
async with self.client.request("GET", "/api/v1/info") as response: | ||
return await response.json() | ||
|
||
async def get_status(self) -> PrinterStatus: | ||
"""Get the printer.""" | ||
async with self.client.request("GET", "/api/v1/status") as response: | ||
return await response.json() | ||
|
||
async def get_job(self) -> JobInfo: | ||
"""Get current job.""" | ||
async with self.client.request("GET", "/api/v1/job") as response: | ||
# when there is no job running we'll an empty document that will fail to parse | ||
if response.status == 204: | ||
return {} | ||
return await response.json() | ||
|
||
# Prusa Link Web UI still uses the old endpoints and it seems that the new v1 endpoint doesn't support this yet | ||
async def get_file(self, path: str) -> bytes: | ||
"""Get a files such as Thumbnails or Icons. Path comes from the current job['file']['refs']['thumbnail']""" | ||
async with self.client.request("GET", path) as response: | ||
return await response.read() |
Oops, something went wrong.