Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions homeassistant/components/prusalink/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from pyprusalink.types_legacy import LegacyPrinterStatus

from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
BinarySensorEntityDescription,
)
Expand All @@ -30,13 +31,38 @@ class PrusaLinkBinarySensorEntityDescription[


BINARY_SENSORS: dict[str, tuple[PrusaLinkBinarySensorEntityDescription, ...]] = {
"status": (
PrusaLinkBinarySensorEntityDescription[PrinterStatus](
key="printer.status_connect",
Comment thread
heikkih marked this conversation as resolved.
Comment thread
heikkih marked this conversation as resolved.
device_class=BinarySensorDeviceClass.CONNECTIVITY,
value_fn=lambda data: data["printer"]["status_connect"]["ok"],
supported_fn=lambda data: (
data["printer"].get("status_connect") is not None
and data["printer"]["status_connect"].get("ok") is not None
),
Comment thread
heikkih marked this conversation as resolved.
),
Comment thread
heikkih marked this conversation as resolved.
Comment thread
heikkih marked this conversation as resolved.
),
"info": (
PrusaLinkBinarySensorEntityDescription[PrinterInfo](
key="info.mmu",
translation_key="mmu",
value_fn=lambda data: data["mmu"],
entity_registry_enabled_default=False,
),
PrusaLinkBinarySensorEntityDescription[PrinterInfo](
key="info.sd_ready",
translation_key="sd_ready",
value_fn=lambda data: data["sd_ready"],
supported_fn=lambda data: data.get("sd_ready") is not None,
entity_registry_enabled_default=False,
),
PrusaLinkBinarySensorEntityDescription[PrinterInfo](
key="info.farm_mode",
translation_key="farm_mode",
value_fn=lambda data: data["farm_mode"],
supported_fn=lambda data: data.get("farm_mode") is not None,
entity_registry_enabled_default=False,
),
Comment thread
heikkih marked this conversation as resolved.
),
}

Expand All @@ -55,6 +81,7 @@ async def async_setup_entry(
entities.extend(
PrusaLinkBinarySensorEntity(coordinator, sensor_description)
for sensor_description in binary_sensors
if sensor_description.supported_fn(coordinator.data)
)

async_add_entities(entities)
Expand Down
11 changes: 11 additions & 0 deletions homeassistant/components/prusalink/icons.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
{
"entity": {
"binary_sensor": {
"farm_mode": {
"default": "mdi:server-network"
},
"mmu": {
"default": "mdi:printer-3d-nozzle-alert"
},
"sd_ready": {
"default": "mdi:micro-sd"
}
},
"button": {
"cancel_job": {
"default": "mdi:cancel"
Expand Down
6 changes: 6 additions & 0 deletions homeassistant/components/prusalink/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@
},
"entity": {
"binary_sensor": {
"farm_mode": {
"name": "Farm mode"
},
"mmu": {
"name": "MMU"
},
"sd_ready": {
"name": "SD card"
}
},
"button": {
Expand Down
4 changes: 4 additions & 0 deletions tests/components/prusalink/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ def mock_info_api() -> Generator[dict[str, Any]]:
"hostname": "PrusaXL",
"min_extrusion_temp": 170,
"location": "Workshop",
"sd_ready": True,
"farm_mode": False,
}
with patch("pyprusalink.PrusaLink.get_info", return_value=resp):
yield resp
Expand Down Expand Up @@ -84,6 +86,7 @@ def mock_get_status_idle() -> Generator[dict[str, Any]]:
"speed": 100,
"fan_hotend": 100,
"fan_print": 75,
"status_connect": {"ok": True, "message": ""},
},
}
with patch("pyprusalink.PrusaLink.get_status", return_value=resp):
Expand Down Expand Up @@ -112,6 +115,7 @@ def mock_get_status_printing() -> Generator[dict[str, Any]]:
"speed": 100,
"fan_hotend": 5000,
"fan_print": 2500,
"status_connect": {"ok": True, "message": ""},
},
}
with patch("pyprusalink.PrusaLink.get_status", return_value=resp):
Expand Down
69 changes: 67 additions & 2 deletions tests/components/prusalink/test_binary_sensor.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
"""Test Prusalink sensors."""

from typing import Any
from unittest.mock import patch

import pytest

from homeassistant.const import STATE_OFF, Platform
from homeassistant.const import STATE_OFF, STATE_ON, Platform
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component

from tests.common import MockConfigEntry


@pytest.fixture(autouse=True)
def setup_binary_sensor_platform_only():
Expand All @@ -20,11 +23,73 @@ def setup_binary_sensor_platform_only():

@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_binary_sensors_no_job(
hass: HomeAssistant, mock_config_entry, mock_api
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_api: None
) -> None:
"""Test sensors while no job active."""
assert await async_setup_component(hass, "prusalink", {})

state = hass.states.get("binary_sensor.mock_title_mmu")
assert state is not None
assert state.state == STATE_OFF
Comment thread
heikkih marked this conversation as resolved.


async def test_status_connect_enabled_by_default(
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_api: None
) -> None:
Comment thread
heikkih marked this conversation as resolved.
"""Connect binary sensor is enabled by default and reflects status_connect.ok."""
assert await async_setup_component(hass, "prusalink", {})

state = hass.states.get("binary_sensor.mock_title_connectivity")
assert state is not None
assert state.state == STATE_ON
Comment thread
heikkih marked this conversation as resolved.


async def test_status_connect_not_created_when_absent(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_api: None,
mock_get_status_idle: dict[str, Any],
) -> None:
"""Connect sensor is not created when status_connect is not in the response."""
del mock_get_status_idle["printer"]["status_connect"]
assert await async_setup_component(hass, "prusalink", {})

assert hass.states.get("binary_sensor.mock_title_connectivity") is None


@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_sd_ready(
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_api: None
) -> None:
"""SD card sensor reflects sd_ready from info endpoint."""
assert await async_setup_component(hass, "prusalink", {})

state = hass.states.get("binary_sensor.mock_title_sd_card")
assert state is not None
assert state.state == STATE_ON


@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_farm_mode(
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_api: None
) -> None:
"""Farm mode sensor reflects farm_mode from info endpoint."""
assert await async_setup_component(hass, "prusalink", {})

state = hass.states.get("binary_sensor.mock_title_farm_mode")
assert state is not None
assert state.state == STATE_OFF


@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_farm_mode_not_created_when_absent(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_api: None,
mock_info_api: dict[str, Any],
) -> None:
"""Farm mode sensor is not created when farm_mode field is absent from info."""
del mock_info_api["farm_mode"]
assert await async_setup_component(hass, "prusalink", {})

assert hass.states.get("binary_sensor.mock_title_farm_mode") is None