Skip to content

Commit

Permalink
Add binary platform to IronOS (home-assistant#132691)
Browse files Browse the repository at this point in the history
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
  • Loading branch information
tr4nt0r and joostlek authored Dec 9, 2024
1 parent 4bb3d61 commit f4e48c3
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 1 deletion.
7 changes: 6 additions & 1 deletion homeassistant/components/iron_os/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@
IronOSSettingsCoordinator,
)

PLATFORMS: list[Platform] = [Platform.NUMBER, Platform.SENSOR, Platform.UPDATE]
PLATFORMS: list[Platform] = [
Platform.BINARY_SENSOR,
Platform.NUMBER,
Platform.SENSOR,
Platform.UPDATE,
]


CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
Expand Down
54 changes: 54 additions & 0 deletions homeassistant/components/iron_os/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""Binary sensor platform for IronOS integration."""

from __future__ import annotations

from enum import StrEnum

from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from . import IronOSConfigEntry
from .coordinator import IronOSLiveDataCoordinator
from .entity import IronOSBaseEntity

# Coordinator is used to centralize the data updates
PARALLEL_UPDATES = 0


class PinecilBinarySensor(StrEnum):
"""Pinecil Binary Sensors."""

TIP_CONNECTED = "tip_connected"


async def async_setup_entry(
hass: HomeAssistant,
entry: IronOSConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up binary sensors from a config entry."""
coordinator = entry.runtime_data.live_data

entity_description = BinarySensorEntityDescription(
key=PinecilBinarySensor.TIP_CONNECTED,
translation_key=PinecilBinarySensor.TIP_CONNECTED,
device_class=BinarySensorDeviceClass.CONNECTIVITY,
)

async_add_entities([IronOSBinarySensorEntity(coordinator, entity_description)])


class IronOSBinarySensorEntity(IronOSBaseEntity, BinarySensorEntity):
"""Representation of a IronOS binary sensor entity."""

coordinator: IronOSLiveDataCoordinator

@property
def is_on(self) -> bool | None:
"""Return true if the binary sensor is on."""
return self.coordinator.has_tip
8 changes: 8 additions & 0 deletions homeassistant/components/iron_os/icons.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
{
"entity": {
"binary_sensor": {
"tip_connected": {
"default": "mdi:pencil-outline",
"state": {
"off": "mdi:pencil-off-outline"
}
}
},
"number": {
"setpoint_temperature": {
"default": "mdi:thermometer"
Expand Down
5 changes: 5 additions & 0 deletions homeassistant/components/iron_os/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
}
},
"entity": {
"binary_sensor": {
"tip_connected": {
"name": "Soldering tip"
}
},
"number": {
"setpoint_temperature": {
"name": "Setpoint temperature"
Expand Down
48 changes: 48 additions & 0 deletions tests/components/iron_os/snapshots/test_binary_sensor.ambr
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# serializer version: 1
# name: test_binary_sensors[binary_sensor.pinecil_soldering_tip-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.pinecil_soldering_tip',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.CONNECTIVITY: 'connectivity'>,
'original_icon': None,
'original_name': 'Soldering tip',
'platform': 'iron_os',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': <PinecilBinarySensor.TIP_CONNECTED: 'tip_connected'>,
'unique_id': 'c0:ff:ee:c0:ff:ee_tip_connected',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensors[binary_sensor.pinecil_soldering_tip-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'connectivity',
'friendly_name': 'Pinecil Soldering tip',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.pinecil_soldering_tip',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
77 changes: 77 additions & 0 deletions tests/components/iron_os/test_binary_sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""Tests for the Pinecil Binary Sensors."""

from collections.abc import AsyncGenerator
from datetime import timedelta
from unittest.mock import AsyncMock, patch

from freezegun.api import FrozenDateTimeFactory
from pynecil import LiveDataResponse
import pytest
from syrupy.assertion import SnapshotAssertion

from homeassistant.components.binary_sensor import STATE_OFF, STATE_ON
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er

from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform


@pytest.fixture(autouse=True)
async def binary_sensor_only() -> AsyncGenerator[None]:
"""Enable only the binary sensor platform."""
with patch(
"homeassistant.components.iron_os.PLATFORMS",
[Platform.BINARY_SENSOR],
):
yield


@pytest.mark.usefixtures(
"entity_registry_enabled_by_default", "mock_pynecil", "ble_device"
)
async def test_binary_sensors(
hass: HomeAssistant,
config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
entity_registry: er.EntityRegistry,
) -> None:
"""Test the Pinecil binary sensor platform."""
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()

assert config_entry.state is ConfigEntryState.LOADED

await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)


@pytest.mark.usefixtures(
"entity_registry_enabled_by_default", "ble_device", "mock_pynecil"
)
async def test_tip_on_off(
hass: HomeAssistant,
config_entry: MockConfigEntry,
mock_pynecil: AsyncMock,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test tip_connected binary sensor on/off states."""

config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()

assert config_entry.state is ConfigEntryState.LOADED

assert hass.states.get("binary_sensor.pinecil_soldering_tip").state == STATE_ON

mock_pynecil.get_live_data.return_value = LiveDataResponse(
live_temp=479,
max_tip_temp_ability=460,
)
freezer.tick(timedelta(seconds=5))
async_fire_time_changed(hass)
await hass.async_block_till_done()

assert hass.states.get("binary_sensor.pinecil_soldering_tip").state == STATE_OFF

0 comments on commit f4e48c3

Please sign in to comment.