mirror of
https://github.com/natekspencer/hacs-oasis_mini.git
synced 2025-12-06 18:44:14 -05:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b32199c334 | ||
|
|
5c49119ae5 | ||
|
|
fbb3012379 | ||
|
|
ac005c70c2 | ||
|
|
873d2d4bb0 | ||
|
|
04be6626a7 | ||
|
|
14223bd1c9 | ||
|
|
1d521bcc18 | ||
|
|
2994e73187 | ||
|
|
e4f6cd2803 | ||
|
|
1cc3585653 | ||
|
|
2f28f7c4bd | ||
|
|
81668c595a | ||
|
|
c17d1682d0 | ||
|
|
f0669c7f63 | ||
|
|
8abfc047f9 | ||
|
|
0df118d18d | ||
|
|
0ebab392fb | ||
|
|
a15548e387 | ||
|
|
b459e3eb9d | ||
|
|
a6ecd740be | ||
|
|
aa7abc2174 | ||
|
|
a548ac5fe2 | ||
|
|
ce22238ae6 | ||
|
|
4ef28fc741 | ||
|
|
cf21a5d995 | ||
|
|
83de1d5606 | ||
|
|
2a92212aad | ||
|
|
ecad472bbd | ||
|
|
886d7598f3 |
@@ -2,11 +2,12 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import async_timeout
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
@@ -67,7 +68,7 @@ class OasisDeviceCoordinator(DataUpdateCoordinator[list[OasisDevice]]):
|
||||
self.attempt += 1
|
||||
|
||||
try:
|
||||
async with asyncio.timeout(30):
|
||||
async with async_timeout.timeout(30):
|
||||
raw_devices = await self.cloud_client.async_get_devices()
|
||||
|
||||
existing_by_serial = {
|
||||
|
||||
@@ -6,12 +6,14 @@ import asyncio
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
import async_timeout
|
||||
|
||||
from homeassistant.const import CONF_ACCESS_TOKEN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
|
||||
from .pyoasiscontrol import OasisCloudClient, OasisDevice
|
||||
from .pyoasiscontrol.const import STATUS_PLAYING, TRACKS
|
||||
from .pyoasiscontrol.const import TRACKS
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -42,26 +44,24 @@ async def add_and_play_track(device: OasisDevice, track: int) -> None:
|
||||
track (int): The track id to add and play.
|
||||
|
||||
Raises:
|
||||
TimeoutError: If the operation does not complete within 10 seconds.
|
||||
async_timeout.TimeoutError: If the operation does not complete within 10 seconds.
|
||||
"""
|
||||
async with asyncio.timeout(10):
|
||||
async with async_timeout.timeout(10):
|
||||
if track not in device.playlist:
|
||||
await device.async_add_track_to_playlist(track)
|
||||
|
||||
# Wait for device state to reflect the newly added track
|
||||
while track not in device.playlist:
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
# Ensure the track is positioned immediately after the current track and select it
|
||||
# Move track to next item in the playlist and then select it
|
||||
if (index := device.playlist.index(track)) != device.playlist_index:
|
||||
# Calculate the position after the current track
|
||||
if index != (
|
||||
_next := min(device.playlist_index + 1, len(device.playlist) - 1)
|
||||
):
|
||||
await device.async_move_track(index, _next)
|
||||
await device.async_change_track(_next)
|
||||
|
||||
if device.status_code != STATUS_PLAYING:
|
||||
if device.status_code != 4:
|
||||
await device.async_play()
|
||||
|
||||
|
||||
|
||||
@@ -23,16 +23,6 @@ from .const import DOMAIN
|
||||
from .entity import OasisDeviceEntity
|
||||
from .helpers import get_track_id
|
||||
from .pyoasiscontrol import OasisDevice
|
||||
from .pyoasiscontrol.const import (
|
||||
STATUS_CENTERING,
|
||||
STATUS_DOWNLOADING,
|
||||
STATUS_ERROR,
|
||||
STATUS_LIVE,
|
||||
STATUS_PAUSED,
|
||||
STATUS_PLAYING,
|
||||
STATUS_STOPPED,
|
||||
STATUS_UPDATING,
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
@@ -140,17 +130,17 @@ class OasisDeviceMediaPlayerEntity(OasisDeviceEntity, MediaPlayerEntity):
|
||||
def state(self) -> MediaPlayerState:
|
||||
"""State of the player."""
|
||||
status_code = self.device.status_code
|
||||
if self.device.error or status_code in (STATUS_ERROR, STATUS_UPDATING):
|
||||
if self.device.error or status_code in (9, 11):
|
||||
return MediaPlayerState.OFF
|
||||
if status_code == STATUS_STOPPED:
|
||||
if status_code == 2:
|
||||
return MediaPlayerState.IDLE
|
||||
if status_code in (STATUS_CENTERING, STATUS_DOWNLOADING):
|
||||
if status_code in (3, 13):
|
||||
return MediaPlayerState.BUFFERING
|
||||
if status_code == STATUS_PLAYING:
|
||||
if status_code == 4:
|
||||
return MediaPlayerState.PLAYING
|
||||
if status_code == STATUS_PAUSED:
|
||||
if status_code == 5:
|
||||
return MediaPlayerState.PAUSED
|
||||
if status_code == STATUS_LIVE:
|
||||
if status_code == 15:
|
||||
return MediaPlayerState.ON
|
||||
return MediaPlayerState.IDLE
|
||||
|
||||
|
||||
@@ -12,19 +12,19 @@ try:
|
||||
TRACKS: Final[dict[int, dict[str, Any]]] = {
|
||||
int(k): v for k, v in json.load(file).items()
|
||||
}
|
||||
except (FileNotFoundError, json.JSONDecodeError, OSError):
|
||||
except Exception: # ignore: broad-except
|
||||
TRACKS = {}
|
||||
|
||||
AUTOPLAY_MAP: Final[dict[str, str]] = {
|
||||
"1": "Off", # display off (disabled) first
|
||||
"0": "Immediately",
|
||||
"2": "After 5 minutes",
|
||||
"3": "After 10 minutes",
|
||||
"4": "After 30 minutes",
|
||||
"6": "After 1 hour",
|
||||
"7": "After 6 hours",
|
||||
"8": "After 12 hours",
|
||||
"5": "After 24 hours", # purposefully placed so time is incrementally displayed
|
||||
"0": "on",
|
||||
"1": "off",
|
||||
"2": "5 minutes",
|
||||
"3": "10 minutes",
|
||||
"4": "30 minutes",
|
||||
"6": "1 hour",
|
||||
"7": "6 hours",
|
||||
"8": "12 hours",
|
||||
"5": "24 hours",
|
||||
}
|
||||
|
||||
ERROR_CODE_MAP: Final[dict[int, str]] = {
|
||||
@@ -94,28 +94,17 @@ LED_EFFECTS: Final[dict[str, str]] = {
|
||||
"41": "Color Comets",
|
||||
}
|
||||
|
||||
STATUS_BOOTING: Final[int] = 0
|
||||
STATUS_STOPPED: Final[int] = 2
|
||||
STATUS_CENTERING: Final[int] = 3
|
||||
STATUS_PLAYING: Final[int] = 4
|
||||
STATUS_PAUSED: Final[int] = 5
|
||||
STATUS_SLEEPING: Final[int] = 6
|
||||
STATUS_ERROR: Final[int] = 9
|
||||
STATUS_UPDATING: Final[int] = 11
|
||||
STATUS_DOWNLOADING: Final[int] = 13
|
||||
STATUS_BUSY: Final[int] = 14
|
||||
STATUS_LIVE: Final[int] = 15
|
||||
|
||||
STATUS_CODE_SLEEPING: Final = 6
|
||||
STATUS_CODE_MAP: Final[dict[int, str]] = {
|
||||
STATUS_BOOTING: "booting",
|
||||
STATUS_STOPPED: "stopped",
|
||||
STATUS_CENTERING: "centering",
|
||||
STATUS_PLAYING: "playing",
|
||||
STATUS_PAUSED: "paused",
|
||||
STATUS_SLEEPING: "sleeping",
|
||||
STATUS_ERROR: "error",
|
||||
STATUS_UPDATING: "updating",
|
||||
STATUS_DOWNLOADING: "downloading",
|
||||
STATUS_BUSY: "busy",
|
||||
STATUS_LIVE: "live",
|
||||
0: "booting",
|
||||
2: "stopped",
|
||||
3: "centering",
|
||||
4: "playing",
|
||||
5: "paused",
|
||||
STATUS_CODE_SLEEPING: "sleeping",
|
||||
9: "error",
|
||||
11: "updating",
|
||||
13: "downloading",
|
||||
14: "busy",
|
||||
15: "live",
|
||||
}
|
||||
|
||||
@@ -10,8 +10,7 @@ from .const import (
|
||||
ERROR_CODE_MAP,
|
||||
LED_EFFECTS,
|
||||
STATUS_CODE_MAP,
|
||||
STATUS_ERROR,
|
||||
STATUS_SLEEPING,
|
||||
STATUS_CODE_SLEEPING,
|
||||
TRACKS,
|
||||
)
|
||||
from .utils import _bit_to_bool, _parse_int, create_svg, decrypt_svg_content
|
||||
@@ -164,7 +163,7 @@ class OasisDevice:
|
||||
Returns:
|
||||
`true` if the device is sleeping, `false` otherwise.
|
||||
"""
|
||||
return self.status_code == STATUS_SLEEPING
|
||||
return self.status_code == STATUS_CODE_SLEEPING
|
||||
|
||||
def attach_client(self, client: OasisClientProtocol) -> None:
|
||||
"""Attach a transport client (MQTT, HTTP, etc.) to this device."""
|
||||
@@ -344,7 +343,7 @@ class OasisDevice:
|
||||
Returns:
|
||||
str: The mapped error message when the device status indicates an error (status code 9); `None` otherwise.
|
||||
"""
|
||||
if self.status_code == STATUS_ERROR:
|
||||
if self.status_code == 9:
|
||||
return ERROR_CODE_MAP.get(self.error, f"Unknown ({self.error})")
|
||||
return None
|
||||
|
||||
|
||||
@@ -76,15 +76,15 @@
|
||||
"autoplay": {
|
||||
"name": "Autoplay",
|
||||
"state": {
|
||||
"1": "Off",
|
||||
"0": "Immediately",
|
||||
"2": "After 5 minutes",
|
||||
"3": "After 10 minutes",
|
||||
"4": "After 30 minutes",
|
||||
"6": "After 1 hour",
|
||||
"7": "After 6 hours",
|
||||
"8": "After 12 hours",
|
||||
"5": "After 24 hours"
|
||||
"0": "on",
|
||||
"1": "off",
|
||||
"2": "5 minutes",
|
||||
"3": "10 minutes",
|
||||
"4": "30 minutes",
|
||||
"6": "1 hour",
|
||||
"7": "6 hours",
|
||||
"8": "12 hours",
|
||||
"5": "24 hours"
|
||||
}
|
||||
},
|
||||
"playlist": {
|
||||
|
||||
@@ -76,15 +76,15 @@
|
||||
"autoplay": {
|
||||
"name": "Autoplay",
|
||||
"state": {
|
||||
"1": "Off",
|
||||
"0": "Immediately",
|
||||
"2": "After 5 minutes",
|
||||
"3": "After 10 minutes",
|
||||
"4": "After 30 minutes",
|
||||
"6": "After 1 hour",
|
||||
"7": "After 6 hours",
|
||||
"8": "After 12 hours",
|
||||
"5": "After 24 hours"
|
||||
"0": "on",
|
||||
"1": "off",
|
||||
"2": "5 minutes",
|
||||
"3": "10 minutes",
|
||||
"4": "30 minutes",
|
||||
"6": "1 hour",
|
||||
"7": "6 hours",
|
||||
"8": "12 hours",
|
||||
"5": "24 hours"
|
||||
}
|
||||
},
|
||||
"playlist": {
|
||||
|
||||
@@ -18,7 +18,6 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from . import OasisDeviceConfigEntry, setup_platform_from_coordinator
|
||||
from .entity import OasisDeviceEntity
|
||||
from .pyoasiscontrol import OasisDevice
|
||||
from .pyoasiscontrol.const import STATUS_UPDATING
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -72,7 +71,7 @@ class OasisDeviceUpdateEntity(OasisDeviceEntity, UpdateEntity):
|
||||
@property
|
||||
def in_progress(self) -> bool | int:
|
||||
"""Update installation progress."""
|
||||
if self.device.status_code == STATUS_UPDATING:
|
||||
if self.device.status_code == 11:
|
||||
return self.device.download_progress
|
||||
return False
|
||||
|
||||
|
||||
Reference in New Issue
Block a user