-
-
Notifications
You must be signed in to change notification settings - Fork 37.5k
Add Squeezebox binary sensors for player alarm status #154491
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
MartinHjelmare
merged 15 commits into
home-assistant:dev
from
wollew:binary_player_alarm_sensors
Dec 5, 2025
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
b3b3560
add binary sensors for upcoming, active and snoozed player alarms
wollew 0a90958
adapt to https://github.com/home-assistant/core/pull/154081
wollew de7e7c6
add tests for player binary sensors
wollew 89ab38f
minor: fix copy/paste remains in docs
wollew 6efb1d3
Update homeassistant/components/squeezebox/binary_sensor.py
wollew f276a07
use f-string instead string concat
wollew eadbb70
remove comment
wollew dc4bac2
return unknown state if player attribute does not exist
wollew 6398c42
Merge branch 'dev' into binary_player_alarm_sensors
wollew ec97acc
Merge branch 'dev' into binary_player_alarm_sensors
wollew 37a176f
apply review suggestions, also fix ignored entity_description
wollew 4178e63
add test to check for correct device class
wollew a25d128
Merge branch 'dev' into binary_player_alarm_sensors
wollew 3fe3d9c
Merge branch 'dev' into binary_player_alarm_sensors
wollew a2ecf8f
Merge branch 'dev' into binary_player_alarm_sensors
wollew File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,35 +1,132 @@ | ||
| """Test squeezebox binary sensors.""" | ||
|
|
||
| from copy import deepcopy | ||
| from unittest.mock import patch | ||
| from datetime import timedelta | ||
| from unittest.mock import MagicMock, patch | ||
|
|
||
| from homeassistant.const import Platform | ||
| from freezegun.api import FrozenDateTimeFactory | ||
| import pytest | ||
|
|
||
| from homeassistant.components.binary_sensor import BinarySensorDeviceClass | ||
| from homeassistant.components.squeezebox.const import PLAYER_UPDATE_INTERVAL | ||
| from homeassistant.const import STATE_OFF, STATE_ON, Platform | ||
| from homeassistant.core import HomeAssistant | ||
|
|
||
| from .conftest import FAKE_QUERY_RESPONSE | ||
|
|
||
| from tests.common import MockConfigEntry | ||
| from tests.common import MockConfigEntry, async_fire_time_changed | ||
|
|
||
|
|
||
| @pytest.fixture(autouse=True) | ||
| def squeezebox_binary_sensor_platform(): | ||
| """Only set up the binary_sensor platform for squeezebox tests.""" | ||
| with patch( | ||
| "homeassistant.components.squeezebox.PLATFORMS", [Platform.BINARY_SENSOR] | ||
| ): | ||
| yield | ||
|
|
||
|
|
||
| async def test_binary_sensor( | ||
| async def test_binary_server_sensor( | ||
| hass: HomeAssistant, | ||
| config_entry: MockConfigEntry, | ||
| ) -> None: | ||
| """Test binary sensor states and attributes.""" | ||
| with ( | ||
| patch( | ||
| "homeassistant.components.squeezebox.PLATFORMS", | ||
| [Platform.BINARY_SENSOR], | ||
| ), | ||
| patch( | ||
| "homeassistant.components.squeezebox.Server.async_query", | ||
| return_value=deepcopy(FAKE_QUERY_RESPONSE), | ||
| ), | ||
| with patch( | ||
|
wollew marked this conversation as resolved.
|
||
| "homeassistant.components.squeezebox.Server.async_query", | ||
| return_value=deepcopy(FAKE_QUERY_RESPONSE), | ||
| ): | ||
| await hass.config_entries.async_setup(config_entry.entry_id) | ||
| await hass.async_block_till_done(wait_background_tasks=True) | ||
|
|
||
| state = hass.states.get("binary_sensor.fakelib_needs_restart") | ||
|
|
||
| assert state is not None | ||
| assert state.state == "off" | ||
| assert state.state == STATE_OFF | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| async def mock_player( | ||
|
wollew marked this conversation as resolved.
|
||
| hass: HomeAssistant, | ||
| config_entry: MockConfigEntry, | ||
| lms: MagicMock, | ||
| ) -> MagicMock: | ||
| """Set up the squeezebox integration and return the mocked player.""" | ||
|
|
||
| # Mock server status data for coordinator update | ||
| # called on update, return something != None to not raise | ||
| lms.async_prepared_status.return_value = { | ||
| "dummy": False, | ||
| } | ||
| with patch("homeassistant.components.squeezebox.Server", return_value=lms): | ||
| await hass.config_entries.async_setup(config_entry.entry_id) | ||
| await hass.async_block_till_done(wait_background_tasks=True) | ||
|
|
||
| # Return the player mock | ||
| return (await lms.async_get_players())[0] | ||
|
|
||
|
|
||
| async def test_player_alarm_sensors_device_class( | ||
| hass: HomeAssistant, | ||
| mock_player: MagicMock, | ||
| ) -> None: | ||
| """Test player alarm binary sensors have correct device class.""" | ||
|
|
||
| # Test alarm upcoming sensor device class | ||
| upcoming_state = hass.states.get("binary_sensor.none_alarm_upcoming") | ||
| assert upcoming_state is not None | ||
| assert upcoming_state.attributes.get("device_class") is None | ||
|
|
||
| # Test alarm active sensor device class | ||
| active_state = hass.states.get("binary_sensor.none_alarm_active") | ||
| assert active_state is not None | ||
| assert ( | ||
| active_state.attributes.get("device_class") == BinarySensorDeviceClass.RUNNING | ||
| ) | ||
|
|
||
| # Test alarm snooze sensor device class | ||
| snooze_state = hass.states.get("binary_sensor.none_alarm_snoozed") | ||
| assert snooze_state is not None | ||
| assert ( | ||
| snooze_state.attributes.get("device_class") == BinarySensorDeviceClass.RUNNING | ||
| ) | ||
|
|
||
|
|
||
| async def test_player_alarm_sensors_state( | ||
| hass: HomeAssistant, | ||
| mock_player: MagicMock, | ||
| freezer: FrozenDateTimeFactory, | ||
| ) -> None: | ||
| """Test player alarm binary sensors with default states.""" | ||
|
|
||
| player = mock_player | ||
|
|
||
| # Test alarm upcoming sensor | ||
| upcoming_state = hass.states.get("binary_sensor.none_alarm_upcoming") | ||
| assert upcoming_state is not None | ||
| assert upcoming_state.state == STATE_ON | ||
|
|
||
| # Test alarm active sensor | ||
| active_state = hass.states.get("binary_sensor.none_alarm_active") | ||
| assert active_state is not None | ||
| assert active_state.state == STATE_OFF | ||
|
|
||
| # Test alarm snooze sensor | ||
| snooze_state = hass.states.get("binary_sensor.none_alarm_snoozed") | ||
| assert snooze_state is not None | ||
| assert snooze_state.state == STATE_OFF | ||
|
|
||
| # Toggle alarm states and verify sensors update | ||
| player.alarm_upcoming = False | ||
| player.alarm_active = True | ||
| player.alarm_snooze = True | ||
| freezer.tick(timedelta(seconds=PLAYER_UPDATE_INTERVAL)) | ||
| async_fire_time_changed(hass) | ||
| await hass.async_block_till_done() | ||
|
|
||
| upcoming_state = hass.states.get("binary_sensor.none_alarm_upcoming") | ||
| assert upcoming_state is not None | ||
| assert upcoming_state.state == STATE_OFF | ||
|
|
||
| active_state = hass.states.get("binary_sensor.none_alarm_active") | ||
| assert active_state is not None | ||
| assert active_state.state == STATE_ON | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.