mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 00:07:10 +00:00
Add binary sensor for smarttub errors (#49364)
This commit is contained in:
parent
64661ee2b7
commit
ffb9ab21c1
@ -1,7 +1,7 @@
|
||||
"""Platform for binary sensor integration."""
|
||||
import logging
|
||||
|
||||
from smarttub import SpaReminder
|
||||
from smarttub import SpaError, SpaReminder
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
@ -11,7 +11,7 @@ from homeassistant.components.binary_sensor import (
|
||||
)
|
||||
from homeassistant.helpers import entity_platform
|
||||
|
||||
from .const import ATTR_REMINDERS, DOMAIN, SMARTTUB_CONTROLLER
|
||||
from .const import ATTR_ERRORS, ATTR_REMINDERS, DOMAIN, SMARTTUB_CONTROLLER
|
||||
from .entity import SmartTubEntity, SmartTubSensorBase
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -19,6 +19,13 @@ _LOGGER = logging.getLogger(__name__)
|
||||
# whether the reminder has been snoozed (bool)
|
||||
ATTR_REMINDER_SNOOZED = "snoozed"
|
||||
|
||||
ATTR_ERROR_CODE = "error_code"
|
||||
ATTR_ERROR_TITLE = "error_title"
|
||||
ATTR_ERROR_DESCRIPTION = "error_description"
|
||||
ATTR_ERROR_TYPE = "error_type"
|
||||
ATTR_CREATED_AT = "created_at"
|
||||
ATTR_UPDATED_AT = "updated_at"
|
||||
|
||||
# how many days to snooze the reminder for
|
||||
ATTR_SNOOZE_DAYS = "days"
|
||||
SNOOZE_REMINDER_SCHEMA = {
|
||||
@ -34,6 +41,7 @@ async def async_setup_entry(hass, entry, async_add_entities):
|
||||
entities = []
|
||||
for spa in controller.spas:
|
||||
entities.append(SmartTubOnline(controller.coordinator, spa))
|
||||
entities.append(SmartTubError(controller.coordinator, spa))
|
||||
entities.extend(
|
||||
SmartTubReminder(controller.coordinator, spa, reminder)
|
||||
for reminder in controller.coordinator.data[spa.id][ATTR_REMINDERS].values()
|
||||
@ -119,3 +127,54 @@ class SmartTubReminder(SmartTubEntity, BinarySensorEntity):
|
||||
"""Snooze this reminder for the specified number of days."""
|
||||
await self.reminder.snooze(days)
|
||||
await self.coordinator.async_request_refresh()
|
||||
|
||||
|
||||
class SmartTubError(SmartTubEntity, BinarySensorEntity):
|
||||
"""Indicates whether an error code is present.
|
||||
|
||||
There may be 0 or more errors. If there are >0, we show the first one.
|
||||
"""
|
||||
|
||||
def __init__(self, coordinator, spa):
|
||||
"""Initialize the entity."""
|
||||
super().__init__(
|
||||
coordinator,
|
||||
spa,
|
||||
"Error",
|
||||
)
|
||||
|
||||
@property
|
||||
def error(self) -> SpaError:
|
||||
"""Return the underlying SpaError object for this entity."""
|
||||
errors = self.coordinator.data[self.spa.id][ATTR_ERRORS]
|
||||
if len(errors) == 0:
|
||||
return None
|
||||
return errors[0]
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return true if an error is signaled."""
|
||||
return self.error is not None
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
"""Return the state attributes."""
|
||||
|
||||
error = self.error
|
||||
|
||||
if error is None:
|
||||
return {}
|
||||
|
||||
return {
|
||||
ATTR_ERROR_CODE: error.code,
|
||||
ATTR_ERROR_TITLE: error.title,
|
||||
ATTR_ERROR_DESCRIPTION: error.description,
|
||||
ATTR_ERROR_TYPE: error.error_type,
|
||||
ATTR_CREATED_AT: error.created_at.isoformat(),
|
||||
ATTR_UPDATED_AT: error.updated_at.isoformat(),
|
||||
}
|
||||
|
||||
@property
|
||||
def device_class(self) -> str:
|
||||
"""Return the device class for this entity."""
|
||||
return DEVICE_CLASS_PROBLEM
|
||||
|
@ -21,6 +21,7 @@ DEFAULT_LIGHT_EFFECT = "purple"
|
||||
# default to 50% brightness
|
||||
DEFAULT_LIGHT_BRIGHTNESS = 128
|
||||
|
||||
ATTR_ERRORS = "errors"
|
||||
ATTR_LIGHTS = "lights"
|
||||
ATTR_PUMPS = "pumps"
|
||||
ATTR_REMINDERS = "reminders"
|
||||
|
@ -16,6 +16,7 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
from .const import (
|
||||
ATTR_ERRORS,
|
||||
ATTR_LIGHTS,
|
||||
ATTR_PUMPS,
|
||||
ATTR_REMINDERS,
|
||||
@ -92,15 +93,17 @@ class SmartTubController:
|
||||
return data
|
||||
|
||||
async def _get_spa_data(self, spa):
|
||||
full_status, reminders = await asyncio.gather(
|
||||
full_status, reminders, errors = await asyncio.gather(
|
||||
spa.get_status_full(),
|
||||
spa.get_reminders(),
|
||||
spa.get_errors(),
|
||||
)
|
||||
return {
|
||||
ATTR_STATUS: full_status,
|
||||
ATTR_PUMPS: {pump.id: pump for pump in full_status.pumps},
|
||||
ATTR_LIGHTS: {light.zone: light for light in full_status.lights},
|
||||
ATTR_REMINDERS: {reminder.id: reminder for reminder in reminders},
|
||||
ATTR_ERRORS: errors,
|
||||
}
|
||||
|
||||
async def async_register_devices(self, entry):
|
||||
|
@ -87,6 +87,8 @@ def mock_spa(spa_state):
|
||||
|
||||
mock_spa.get_reminders.return_value = [mock_filter_reminder]
|
||||
|
||||
mock_spa.get_errors.return_value = []
|
||||
|
||||
return mock_spa
|
||||
|
||||
|
||||
|
@ -1,5 +1,11 @@
|
||||
"""Test the SmartTub binary sensor platform."""
|
||||
from homeassistant.components.binary_sensor import STATE_OFF
|
||||
from datetime import datetime
|
||||
from unittest.mock import create_autospec
|
||||
|
||||
import pytest
|
||||
import smarttub
|
||||
|
||||
from homeassistant.components.binary_sensor import STATE_OFF, STATE_ON
|
||||
|
||||
|
||||
async def test_binary_sensors(spa, setup_entry, hass):
|
||||
@ -10,6 +16,11 @@ async def test_binary_sensors(spa, setup_entry, hass):
|
||||
# disabled by default
|
||||
assert state is None
|
||||
|
||||
entity_id = f"binary_sensor.{spa.brand}_{spa.model}_error"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state is not None
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
|
||||
async def test_reminders(spa, setup_entry, hass):
|
||||
"""Test the reminder sensor."""
|
||||
@ -21,6 +32,37 @@ async def test_reminders(spa, setup_entry, hass):
|
||||
assert state.attributes["snoozed"] is False
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_error(spa):
|
||||
"""Mock error."""
|
||||
error = create_autospec(smarttub.SpaError, instance=True)
|
||||
error.code = 11
|
||||
error.title = "Flow Switch Stuck Open"
|
||||
error.description = None
|
||||
error.active = True
|
||||
error.created_at = datetime.now()
|
||||
error.updated_at = datetime.now()
|
||||
error.error_type = "TUB_ERROR"
|
||||
return error
|
||||
|
||||
|
||||
async def test_error(spa, hass, config_entry, mock_error):
|
||||
"""Test the error sensor."""
|
||||
|
||||
spa.get_errors.return_value = [mock_error]
|
||||
|
||||
config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = f"binary_sensor.{spa.brand}_{spa.model}_error"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state is not None
|
||||
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes["error_code"] == 11
|
||||
|
||||
|
||||
async def test_snooze(spa, setup_entry, hass):
|
||||
"""Test snoozing a reminder."""
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user