From 6602e4a046a723b415c05342c391dbca16491542 Mon Sep 17 00:00:00 2001 From: Owen Voke Date: Tue, 26 Nov 2024 17:14:46 +0000 Subject: [PATCH] feat: add `use_spool_filament` service --- custom_components/spoolman/__init__.py | 15 +++++++++- .../spoolman/classes/spoolman_api.py | 28 +++++++++++++++++++ custom_components/spoolman/const.py | 1 + custom_components/spoolman/schema_helper.py | 9 ++++++ custom_components/spoolman/services.yaml | 18 ++++++++++++ 5 files changed, 70 insertions(+), 1 deletion(-) diff --git a/custom_components/spoolman/__init__.py b/custom_components/spoolman/__init__.py index f3ca992..cb616f7 100644 --- a/custom_components/spoolman/__init__.py +++ b/custom_components/spoolman/__init__.py @@ -7,7 +7,8 @@ from custom_components.spoolman.schema_helper import SchemaHelper -from .const import DOMAIN, SPOOLMAN_API_WRAPPER, SPOOLMAN_PATCH_SPOOL_SERVICENAME +from .const import (DOMAIN, SPOOLMAN_API_WRAPPER, SPOOLMAN_PATCH_SPOOL_SERVICENAME, + SPOOLMAN_USE_SPOOL_FILAMENT_SERVICENAME) from .coordinator import SpoolManCoordinator _LOGGER = logging.getLogger(__name__) @@ -47,8 +48,20 @@ async def handle_spoolman_patch_spool(call): _LOGGER.error(f"Failed to patch spool: {e}") raise HomeAssistantError(f"Failed to patch spool: {e}") + async def handle_spoolman_use_spool_filament(call): + spool_id = call.data.get('id') + data = {key: call.data[key] for key in call.data if key != 'id'} + _LOGGER.info(f"Use spool filament called with id: {spool_id} and data: {data}") + + try: + await coordinator.spoolman_api.use_spool_filament(spool_id, data) + except Exception as e: + _LOGGER.error(f"Failed to use filament: {e}") + raise HomeAssistantError(f"Failed to use filament: {e}") + hass.services.async_register(DOMAIN, SPOOLMAN_PATCH_SPOOL_SERVICENAME, handle_spoolman_patch_spool, schema=SchemaHelper.get_spoolman_patch_spool_schema()) + hass.services.async_register(DOMAIN, SPOOLMAN_USE_SPOOL_FILAMENT_SERVICENAME, handle_spoolman_use_spool_filament, schema=SchemaHelper.get_spoolman_use_spool_filament_schema()) return True diff --git a/custom_components/spoolman/classes/spoolman_api.py b/custom_components/spoolman/classes/spoolman_api.py index 59217d1..9406ea3 100644 --- a/custom_components/spoolman/classes/spoolman_api.py +++ b/custom_components/spoolman/classes/spoolman_api.py @@ -112,3 +112,31 @@ async def patch_spool(self, spool_id, data): except Exception as e: _LOGGER.error(f"An unexpected error occurred: {e}") raise + + async def use_spool_filament(self, spool_id, data): + """Update the spool filament usage with the specified ID.""" + _LOGGER.info(f"SpoolmanAPI: patch_spool {spool_id} with data {data}") + + if "use_length" in data and "use_weight" in data: + if data["use_length"] > 0 and data["use_weight"] > 0: + raise ValueError("use_length and use_weight cannot be used together. Please use only one of them.") + + url = f"{self.base_url}/spool/{spool_id}/use" + try: + async with aiohttp.ClientSession() as session, session.put(url, json=data) as response: + response.raise_for_status() + response_data = await response.json() + _LOGGER.debug("SpoolmanAPI: use_spool_filament response %s", response_data) + return response_data + except aiohttp.ClientResponseError as e: + _LOGGER.error(f"HTTP error occurred: {e.status} {e.message}") + raise + except aiohttp.ClientConnectionError as e: + _LOGGER.error(f"Connection error occurred: {e}") + raise + except aiohttp.ClientError as e: + _LOGGER.error(f"Client error occurred: {e}") + raise + except Exception as e: + _LOGGER.error(f"An unexpected error occurred: {e}") + raise diff --git a/custom_components/spoolman/const.py b/custom_components/spoolman/const.py index 6b40ab3..71de15b 100644 --- a/custom_components/spoolman/const.py +++ b/custom_components/spoolman/const.py @@ -23,3 +23,4 @@ KLIPPER_URL_DESC = "klipper_url_desc" SPOOLMAN_PATCH_SPOOL_SERVICENAME = "patch_spool" +SPOOLMAN_USE_SPOOL_FILAMENT_SERVICENAME = "use_spool_filament" diff --git a/custom_components/spoolman/schema_helper.py b/custom_components/spoolman/schema_helper.py index 3d8a823..14dee68 100644 --- a/custom_components/spoolman/schema_helper.py +++ b/custom_components/spoolman/schema_helper.py @@ -38,6 +38,15 @@ def get_spoolman_patch_spool_schema(): vol.Optional('extra'): vol.Schema({}, extra=vol.ALLOW_EXTRA), }) + @staticmethod + def get_spoolman_use_spool_filament_schema(): + """Get the schema for the spoolman_use_spool_filament service.""" + return vol.Schema({ + vol.Required('id'): cv.string, + vol.Optional('use_length'): vol.Coerce(float), + vol.Optional('use_weight'): vol.Coerce(float), + }) + @staticmethod def get_config_schema(get_values=False, config_data=None): """Get the form for config and options flows.""" diff --git a/custom_components/spoolman/services.yaml b/custom_components/spoolman/services.yaml index fdcc29b..7664dc5 100644 --- a/custom_components/spoolman/services.yaml +++ b/custom_components/spoolman/services.yaml @@ -61,3 +61,21 @@ patch_spool: example: property1: "string" property2: "string" + +use_spool_filament: + name: "Use Spool Filament" + description: "Use a weight (or length) of filament for a spool." + fields: + id: + name: "ID" + description: "The ID of the spool." + example: 123 + required: true + use_weight: + name: "Used Weight" + description: "The weight of the filament to use from the spool (in g)." + example: 10 + use_length: + name: "Used Length" + description: "The length of the filament to use from the spool (in mm)." + example: 100