From cce725f82521c0b5299e731f1bc04e6c88780eab Mon Sep 17 00:00:00 2001 From: Eric Tremblay Date: Mon, 25 Mar 2024 15:32:36 -0400 Subject: [PATCH] Add support for multiple extruder The patch add support for multiple extruder, the klipper convention to do so is quite simple, the first one is called extruder and the others are named extruder1, extruder2 and so on. By moving the extruder sensors to the optional sensor where we use the object list it's quite easy to support multiple one --- custom_components/moonraker/sensor.py | 78 +++++++++++++++------------ docs/entities/sensors.rst | 3 ++ tests/conftest.py | 9 ++++ tests/test_sensor.py | 3 ++ 4 files changed, 60 insertions(+), 33 deletions(-) diff --git a/custom_components/moonraker/sensor.py b/custom_components/moonraker/sensor.py index 020ceae..92efa53 100755 --- a/custom_components/moonraker/sensor.py +++ b/custom_components/moonraker/sensor.py @@ -1,4 +1,5 @@ """Sensor platform for Moonraker integration.""" + import logging from collections.abc import Callable from dataclasses import dataclass @@ -77,28 +78,6 @@ class MoonrakerSensorDescription(SensorEntityDescription): else "", subscriptions=[("display_status", "message")], ), - MoonrakerSensorDescription( - key="extruder_temp", - name="Extruder Temperature", - value_fn=lambda sensor: float( - sensor.coordinator.data["status"]["extruder"]["temperature"] or 0.0 - ), - subscriptions=[("extruder", "temperature")], - icon="mdi:printer-3d-nozzle-heat", - unit=UnitOfTemperature.CELSIUS, - state_class=SensorStateClass.MEASUREMENT, - ), - MoonrakerSensorDescription( - key="extruder_target", - name="Extruder Target", - value_fn=lambda sensor: float( - sensor.coordinator.data["status"]["extruder"]["target"] or 0.0 - ), - subscriptions=[("extruder", "target")], - icon="mdi:printer-3d-nozzle-heat", - unit=UnitOfTemperature.CELSIUS, - state_class=SensorStateClass.MEASUREMENT, - ), MoonrakerSensorDescription( key="bed_target", name="Bed Target", @@ -256,17 +235,6 @@ class MoonrakerSensorDescription(SensorEntityDescription): unit=PERCENTAGE, state_class=SensorStateClass.MEASUREMENT, ), - MoonrakerSensorDescription( - key="extruder_power", - name="Extruder Power", - value_fn=lambda sensor: int( - sensor.coordinator.data["status"]["extruder"]["power"] * 100 - ), - subscriptions=[("extruder", "power")], - icon="mdi:flash", - unit=PERCENTAGE, - state_class=SensorStateClass.MEASUREMENT, - ), MoonrakerSensorDescription( key="total_layer", name="Total Layer", @@ -423,6 +391,50 @@ async def async_setup_optional_sensors(coordinator, entry, async_add_entities): unit=PERCENTAGE, ) sensors.append(desc) + elif obj.startswith("extruder"): + desc = MoonrakerSensorDescription( + key=f"{obj}_temp", + status_key=obj, + name=f"{obj} Temperature".title(), + value_fn=lambda sensor: float( + sensor.coordinator.data["status"][sensor.status_key]["temperature"] + or 0.0 + ), + subscriptions=[(obj, "temperature")], + icon="mdi:printer-3d-nozzle-heat", + unit=UnitOfTemperature.CELSIUS, + state_class=SensorStateClass.MEASUREMENT, + ) + sensors.append(desc) + + desc = MoonrakerSensorDescription( + key=f"{obj}_target", + status_key=obj, + name=f"{obj} Target".title(), + value_fn=lambda sensor: float( + sensor.coordinator.data["status"][sensor.status_key]["target"] + or 0.0 + ), + subscriptions=[(obj, "target")], + icon="mdi:printer-3d-nozzle-heat", + unit=UnitOfTemperature.CELSIUS, + state_class=SensorStateClass.MEASUREMENT, + ) + sensors.append(desc) + + desc = MoonrakerSensorDescription( + key=f"{obj}_power", + status_key=obj, + name=f"{obj} Power".title(), + value_fn=lambda sensor: int( + sensor.coordinator.data["status"][sensor.status_key]["power"] * 100 + ), + subscriptions=[(obj, "power")], + icon="mdi:flash", + unit=PERCENTAGE, + state_class=SensorStateClass.MEASUREMENT, + ) + sensors.append(desc) coordinator.load_sensor_data(sensors) await coordinator.async_refresh() diff --git a/docs/entities/sensors.rst b/docs/entities/sensors.rst index e887402..94e6a5c 100644 --- a/docs/entities/sensors.rst +++ b/docs/entities/sensors.rst @@ -33,12 +33,15 @@ Sensors that are added on integration startup. - From Moonraker API (display_status, message) * - Extruder Temperature - Extruder Temperature + - Multiple extruders are supported - From Moonraker API (extruder, temperature) * - Extruder Temperature Target - Extruder Temperature Target + - Multiple extruders are supported - From Moonraker API (extruder, target) * - Extruder Power - Extruder current power consumption (in %). 100% = Max, 0% = close + - Multiple extruders are supported - From Moonraker API (extruder, power) * - Bed Temperature - Bed Temperature diff --git a/tests/conftest.py b/tests/conftest.py index aa4c5de..1795773 100755 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -85,6 +85,14 @@ def get_data_fixture(): "pressure_advance": 0.325, "smooth_time": 0.04, }, + "extruder1": { + "temperature": 220.01, + "target": 220.0, + "power": 0.6667108063925052, + "can_extrude": True, + "pressure_advance": 0.325, + "smooth_time": 0.04, + }, "heater_bed": { "temperature": 60.01, "target": 60.0, @@ -269,6 +277,7 @@ def get_printer_objects_list_fixture(): "manual_probe", "toolhead", "extruder", + "extruder1", "temperature_fan fan_temp", "temperature_host host_temp", "bme280 bme280_temp", diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 219f284..2f651cd 100755 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -1,4 +1,5 @@ """Test moonraker sensor.""" + import datetime as dt from unittest.mock import patch @@ -75,6 +76,8 @@ async def test_sensor_services_update(hass, get_data): ("mainsail_bed_temperature", "60.01"), ("mainsail_extruder_target", "205.0"), ("mainsail_extruder_temperature", "205.02"), + ("mainsail_extruder1_target", "220.0"), + ("mainsail_extruder1_temperature", "220.01"), ("mainsail_progress", "90"), ("mainsail_printer_state", "ready"), ("mainsail_filename", "CE3E3V2_picture_frame_holder.gcode"),