python-linkplay 0.2.13__py3-none-any.whl → 0.2.14__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- linkplay/__version__.py +1 -1
- linkplay/consts.py +1 -1
- linkplay/exceptions.py +11 -2
- linkplay/manufacturers.py +9 -1
- linkplay/utils.py +25 -8
- {python_linkplay-0.2.13.dist-info → python_linkplay-0.2.14.dist-info}/METADATA +1 -1
- python_linkplay-0.2.14.dist-info/RECORD +16 -0
- python_linkplay-0.2.13.dist-info/RECORD +0 -16
- {python_linkplay-0.2.13.dist-info → python_linkplay-0.2.14.dist-info}/WHEEL +0 -0
- {python_linkplay-0.2.13.dist-info → python_linkplay-0.2.14.dist-info}/licenses/LICENSE +0 -0
- {python_linkplay-0.2.13.dist-info → python_linkplay-0.2.14.dist-info}/top_level.txt +0 -0
linkplay/__version__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = '0.2.
|
1
|
+
__version__ = '0.2.14'
|
linkplay/consts.py
CHANGED
@@ -4,7 +4,7 @@ from enum import IntFlag, StrEnum
|
|
4
4
|
LOGGER = logging.getLogger("linkplay")
|
5
5
|
|
6
6
|
API_ENDPOINT: str = "{}/httpapi.asp?command={}"
|
7
|
-
API_TIMEOUT: int =
|
7
|
+
API_TIMEOUT: int = 10
|
8
8
|
UNKNOWN_TRACK_PLAYING: str = "Unknown"
|
9
9
|
UPNP_DEVICE_TYPE = "urn:schemas-upnp-org:device:MediaRenderer:1"
|
10
10
|
TCPPORT = 8899
|
linkplay/exceptions.py
CHANGED
@@ -1,12 +1,21 @@
|
|
1
|
+
"""This module defines custom exceptions for the LinkPlay integration."""
|
2
|
+
|
3
|
+
|
1
4
|
class LinkPlayException(Exception):
|
2
|
-
|
5
|
+
"""Base exception for LinkPlay errors."""
|
3
6
|
|
4
7
|
|
5
8
|
class LinkPlayRequestException(LinkPlayException):
|
6
|
-
|
9
|
+
"""Exception raised for errors in LinkPlay requests."""
|
10
|
+
|
11
|
+
|
12
|
+
class LinkPlayRequestCancelledException(LinkPlayException):
|
13
|
+
"""Exception raised when a LinkPlay request is cancelled."""
|
7
14
|
|
8
15
|
|
9
16
|
class LinkPlayInvalidDataException(LinkPlayException):
|
17
|
+
"""Exception raised for invalid data received from LinkPlay endpoints."""
|
18
|
+
|
10
19
|
def __init__(self, message: str = "Invalid data received", data: str | None = None):
|
11
20
|
super().__init__(message)
|
12
21
|
self.data = data
|
linkplay/manufacturers.py
CHANGED
@@ -37,11 +37,15 @@ MODELS_WIIM_AMP: Final[str] = "WiiM Amp"
|
|
37
37
|
MODELS_WIIM_MINI: Final[str] = "WiiM Mini"
|
38
38
|
MODELS_WIIM_PRO: Final[str] = "WiiM Pro"
|
39
39
|
MODELS_WIIM_PRO_PLUS: Final[str] = "WiiM Pro Plus"
|
40
|
+
MODELS_WIIM_AMP_PRO: Final[str] = "WiiM Amp Pro"
|
41
|
+
MODELS_WIIM_ULTRA: Final[str] = "WiiM Ultra"
|
42
|
+
MODELS_WIIM_AMP_ULTRA: Final[str] = "WiiM Amp Ultra"
|
43
|
+
MODELS_WIIM_CI_MOD_S: Final[str] = "WiiM CI MOD S"
|
44
|
+
MODELS_WIIM_CI_MOD_A80: Final[str] = "WiiM CI MOD A80"
|
40
45
|
MODELS_GGMM_GGMM_E2: Final[str] = "GGMM E2"
|
41
46
|
MODELS_MEDION_MD_43970: Final[str] = "Life P66970 (MD 43970)"
|
42
47
|
MODELS_WR320: Final[str] = "WR320"
|
43
48
|
MODELS_WS350: Final[str] = "WS350"
|
44
|
-
MODELS_WIIM_AMP_PRO: Final[str] = "WiiM Amp Pro"
|
45
49
|
MODELS_MUZO_COBBLESTONE: Final[str] = "MUZO Cobblestone Wi-Fi Audio Receiver"
|
46
50
|
MODELS_AUDIOPRO_C3: Final[str] = "C3"
|
47
51
|
MODELS_AUDIOPRO_C10: Final[str] = "C10"
|
@@ -95,6 +99,10 @@ PROJECTID_LOOKUP: Final[dict[str, tuple[str, str]]] = {
|
|
95
99
|
"AudioPro_C10": (MANUFACTURER_AUDIOPRO, MODELS_AUDIOPRO_C10),
|
96
100
|
"AudioPro_A10": (MANUFACTURER_AUDIOPRO, MODELS_AUDIOPRO_A10),
|
97
101
|
"U-AIO3v2": (MANUFACTURER_TRIANGLE, MODELS_TRIANGLE_AIO_3),
|
102
|
+
"WiiM_Ultra": (MANUFACTURER_WIIM, MODELS_WIIM_ULTRA),
|
103
|
+
"WiiM_Amp_Ultra": (MANUFACTURER_WIIM, MODELS_WIIM_AMP_ULTRA),
|
104
|
+
"WiiM_CI_MOD_S": (MANUFACTURER_WIIM, MODELS_WIIM_CI_MOD_S),
|
105
|
+
"WiiM_CI_MOD_A80": (MANUFACTURER_WIIM, MODELS_WIIM_CI_MOD_A80),
|
98
106
|
}
|
99
107
|
|
100
108
|
|
linkplay/utils.py
CHANGED
@@ -10,20 +10,25 @@ from http import HTTPStatus
|
|
10
10
|
|
11
11
|
import aiofiles
|
12
12
|
import async_timeout
|
13
|
-
from aiohttp import ClientError, ClientSession, TCPConnector
|
13
|
+
from aiohttp import ClientError, ClientSession, ClientTimeout, TCPConnector
|
14
14
|
from appdirs import AppDirs
|
15
15
|
from deprecated import deprecated
|
16
16
|
|
17
17
|
from linkplay.consts import (
|
18
18
|
API_ENDPOINT,
|
19
19
|
API_TIMEOUT,
|
20
|
+
LOGGER,
|
20
21
|
MTLS_CERTIFICATE_CONTENTS,
|
21
22
|
TCP_MESSAGE_LENGTH,
|
22
23
|
EqualizerMode,
|
23
24
|
PlayerAttribute,
|
24
25
|
PlayingStatus,
|
25
26
|
)
|
26
|
-
from linkplay.exceptions import
|
27
|
+
from linkplay.exceptions import (
|
28
|
+
LinkPlayInvalidDataException,
|
29
|
+
LinkPlayRequestCancelledException,
|
30
|
+
LinkPlayRequestException,
|
31
|
+
)
|
27
32
|
|
28
33
|
|
29
34
|
async def session_call_api(endpoint: str, session: ClientSession, command: str) -> str:
|
@@ -45,18 +50,29 @@ async def session_call_api(endpoint: str, session: ClientSession, command: str)
|
|
45
50
|
try:
|
46
51
|
async with async_timeout.timeout(API_TIMEOUT):
|
47
52
|
response = await session.get(url)
|
48
|
-
|
49
|
-
|
53
|
+
if response.status != HTTPStatus.OK:
|
54
|
+
raise LinkPlayRequestException(
|
55
|
+
f"Unexpected HTTPStatus {response.status} received from '{url}'"
|
56
|
+
)
|
57
|
+
return await response.text()
|
58
|
+
|
59
|
+
except ClientError as error:
|
60
|
+
LOGGER.warning("ClientError for %s: %s", url, error)
|
50
61
|
raise LinkPlayRequestException(
|
51
62
|
f"{error} error requesting data from '{url}'"
|
52
63
|
) from error
|
53
64
|
|
54
|
-
|
65
|
+
except asyncio.TimeoutError as error:
|
66
|
+
LOGGER.warning("Timeout for %s: %s", url, error)
|
55
67
|
raise LinkPlayRequestException(
|
56
|
-
f"
|
57
|
-
)
|
68
|
+
f"{error} error requesting data from '{url}'"
|
69
|
+
) from error
|
58
70
|
|
59
|
-
|
71
|
+
except asyncio.CancelledError as error:
|
72
|
+
LOGGER.warning("Cancelled for %s: %s", url, error)
|
73
|
+
raise LinkPlayRequestCancelledException(
|
74
|
+
f"{error} error requesting data from '{url}'"
|
75
|
+
) from error
|
60
76
|
|
61
77
|
|
62
78
|
async def session_call_api_json(
|
@@ -81,6 +97,7 @@ async def session_call_api_json(
|
|
81
97
|
return json.loads(result) # type: ignore
|
82
98
|
except json.JSONDecodeError as jsonexc:
|
83
99
|
url = API_ENDPOINT.format(endpoint, command)
|
100
|
+
LOGGER.warning("Unexpected json for %s: %s", url, jsonexc)
|
84
101
|
raise LinkPlayInvalidDataException(
|
85
102
|
message=f"Unexpected JSON ({result}) received from '{url}'", data=result
|
86
103
|
) from jsonexc
|
@@ -0,0 +1,16 @@
|
|
1
|
+
linkplay/__init__.py,sha256=y9ZehEq-KhS3cwn-PUpwVSJGfDUx7e5wf_G6guODcTk,56
|
2
|
+
linkplay/__main__.py,sha256=Wcza80QaWfOaHjyJEfQYhB9kiPLE0NOqIj4zVWv2Nqs,577
|
3
|
+
linkplay/__version__.py,sha256=rfy0OFG8rEvQ6bRSAURO04IijvDzG0it93O1BM4V4E0,23
|
4
|
+
linkplay/bridge.py,sha256=Id0yDa807qo0Jv_0IUIwnok0EuUa-0z01rABul4AcXs,21834
|
5
|
+
linkplay/consts.py,sha256=PYjegdpzXov7UpUaRxgbIe-IFdbt_Gy0qGfZuMzT_8I,15781
|
6
|
+
linkplay/controller.py,sha256=U370dMVl-E7iIhDC1wWmsrnFcdrWso84K0vkImsgCTo,4430
|
7
|
+
linkplay/discovery.py,sha256=NnkO9gknp3Cyff7830zBu1LwyhkkWCdhDbEDbAwF8D8,4610
|
8
|
+
linkplay/endpoint.py,sha256=_gelW0cDWt0SC8EApwaKIVh_YJIMNiOkfrLR_RYW7aM,2677
|
9
|
+
linkplay/exceptions.py,sha256=9zBBhNdPj6qQj1SD1nkhruhN8mhlkuTaiUj87FEqzJM,682
|
10
|
+
linkplay/manufacturers.py,sha256=UZk8wWZGPOi9pN9wnqOKbcWZBkZZHljkODWPvcNpZPA,6206
|
11
|
+
linkplay/utils.py,sha256=otPFrx5c0MFmvXiiZSVUFaIBFG-YVMRi4SeInq0T4rY,10128
|
12
|
+
python_linkplay-0.2.14.dist-info/licenses/LICENSE,sha256=bgEtxMyjEHX_4uwaAY3GCFTm234D4AOZ5dM15sk26ms,1073
|
13
|
+
python_linkplay-0.2.14.dist-info/METADATA,sha256=kfVa_GqjRt0sil1S2vFcpaaaz7Zaww12kcw0ejI3rl8,3261
|
14
|
+
python_linkplay-0.2.14.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
15
|
+
python_linkplay-0.2.14.dist-info/top_level.txt,sha256=CpSaOVPTzJf5TVIL7MrotSCR34gcIOQy-11l4zGmxxM,9
|
16
|
+
python_linkplay-0.2.14.dist-info/RECORD,,
|
@@ -1,16 +0,0 @@
|
|
1
|
-
linkplay/__init__.py,sha256=y9ZehEq-KhS3cwn-PUpwVSJGfDUx7e5wf_G6guODcTk,56
|
2
|
-
linkplay/__main__.py,sha256=Wcza80QaWfOaHjyJEfQYhB9kiPLE0NOqIj4zVWv2Nqs,577
|
3
|
-
linkplay/__version__.py,sha256=y7T0aODMp6lh_FsLCIWZvm04exJp-NxszVrIpCH9tLE,23
|
4
|
-
linkplay/bridge.py,sha256=Id0yDa807qo0Jv_0IUIwnok0EuUa-0z01rABul4AcXs,21834
|
5
|
-
linkplay/consts.py,sha256=J2tocNaSyb5xs-qY0PqvOLl8_DzwarWZjTi-F9tXY4U,15780
|
6
|
-
linkplay/controller.py,sha256=U370dMVl-E7iIhDC1wWmsrnFcdrWso84K0vkImsgCTo,4430
|
7
|
-
linkplay/discovery.py,sha256=NnkO9gknp3Cyff7830zBu1LwyhkkWCdhDbEDbAwF8D8,4610
|
8
|
-
linkplay/endpoint.py,sha256=_gelW0cDWt0SC8EApwaKIVh_YJIMNiOkfrLR_RYW7aM,2677
|
9
|
-
linkplay/exceptions.py,sha256=UHcV0Yok0hdM0MYgHRwTWnMJ612Ts0iJvMFHX-IxmNo,312
|
10
|
-
linkplay/manufacturers.py,sha256=dQOxyMyw1sHu31QGlbbtbNk6Xkvsp1vpc6UsojiXBrg,5746
|
11
|
-
linkplay/utils.py,sha256=fZHGnUM4XFrQ7MM6guHhaEmxJbVlwilbwoZXvXwSfMs,9480
|
12
|
-
python_linkplay-0.2.13.dist-info/licenses/LICENSE,sha256=bgEtxMyjEHX_4uwaAY3GCFTm234D4AOZ5dM15sk26ms,1073
|
13
|
-
python_linkplay-0.2.13.dist-info/METADATA,sha256=qRo-DrimYo1k60u2lRWA46CG0LmLAtqOZ1AfZ0nGxMw,3261
|
14
|
-
python_linkplay-0.2.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
15
|
-
python_linkplay-0.2.13.dist-info/top_level.txt,sha256=CpSaOVPTzJf5TVIL7MrotSCR34gcIOQy-11l4zGmxxM,9
|
16
|
-
python_linkplay-0.2.13.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|