python-openhab-rest-client 0.1.0__tar.gz → 0.1.1__tar.gz
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.
- {python_openhab_rest_client-0.1.0/python_openhab_rest_client.egg-info → python_openhab_rest_client-0.1.1}/PKG-INFO +1 -1
- python_openhab_rest_client-0.1.1/openhab/Actions.py +100 -0
- python_openhab_rest_client-0.1.1/openhab/Addons.py +405 -0
- python_openhab_rest_client-0.1.1/openhab/Audio.py +152 -0
- python_openhab_rest_client-0.1.1/openhab/Auth.py +241 -0
- python_openhab_rest_client-0.1.1/openhab/ChannelTypes.py +129 -0
- {python_openhab_rest_client-0.1.0 → python_openhab_rest_client-0.1.1}/openhab/Client.py +38 -6
- python_openhab_rest_client-0.1.1/openhab/ConfigDescriptions.py +94 -0
- python_openhab_rest_client-0.1.1/openhab/Discovery.py +69 -0
- python_openhab_rest_client-0.1.1/openhab/Events.py +791 -0
- python_openhab_rest_client-0.1.1/openhab/Iconsets.py +42 -0
- python_openhab_rest_client-0.1.1/openhab/Inbox.py +178 -0
- python_openhab_rest_client-0.1.1/openhab/Items.py +708 -0
- python_openhab_rest_client-0.1.1/openhab/Links.py +258 -0
- python_openhab_rest_client-0.1.1/openhab/Logging.py +138 -0
- python_openhab_rest_client-0.1.1/openhab/ModuleTypes.py +93 -0
- python_openhab_rest_client-0.1.1/openhab/Persistence.py +298 -0
- {python_openhab_rest_client-0.1.0 → python_openhab_rest_client-0.1.1}/openhab/ProfileTypes.py +24 -2
- python_openhab_rest_client-0.1.1/openhab/Rules.py +615 -0
- python_openhab_rest_client-0.1.1/openhab/Services.py +219 -0
- python_openhab_rest_client-0.1.1/openhab/Sitemaps.py +279 -0
- python_openhab_rest_client-0.1.1/openhab/Systeminfo.py +74 -0
- python_openhab_rest_client-0.1.1/openhab/Tags.py +214 -0
- python_openhab_rest_client-0.1.1/openhab/Templates.py +83 -0
- python_openhab_rest_client-0.1.1/openhab/ThingTypes.py +89 -0
- python_openhab_rest_client-0.1.1/openhab/Things.py +512 -0
- python_openhab_rest_client-0.1.1/openhab/Transformations.py +177 -0
- python_openhab_rest_client-0.1.1/openhab/UI.py +208 -0
- python_openhab_rest_client-0.1.1/openhab/UUID.py +39 -0
- python_openhab_rest_client-0.1.1/openhab/Voice.py +396 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Actions.py +42 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Addons.py +111 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Audio.py +50 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Auth.py +71 -0
- python_openhab_rest_client-0.1.1/openhab/tests/ChannelEvents.py +30 -0
- python_openhab_rest_client-0.1.1/openhab/tests/ChannelTypes.py +42 -0
- python_openhab_rest_client-0.1.1/openhab/tests/ConfigDescriptions.py +32 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Discovery.py +32 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Events.py +49 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Iconsets.py +20 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Inbox.py +60 -0
- python_openhab_rest_client-0.1.1/openhab/tests/InboxEvents.py +37 -0
- python_openhab_rest_client-0.1.1/openhab/tests/ItemEvents.py +121 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Items.py +150 -0
- python_openhab_rest_client-0.1.1/openhab/tests/LinkEvents.py +30 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Links.py +74 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Logging.py +47 -0
- python_openhab_rest_client-0.1.1/openhab/tests/ModuleTypes.py +30 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Persistence.py +92 -0
- python_openhab_rest_client-0.1.1/openhab/tests/ProfileTypes.py +21 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Rules.py +83 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Services.py +72 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Sitemaps.py +72 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Systeminfo.py +33 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Tags.py +62 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Templates.py +34 -0
- python_openhab_rest_client-0.1.1/openhab/tests/ThingEvents.py +61 -0
- python_openhab_rest_client-0.1.1/openhab/tests/ThingTypes.py +35 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Things.py +81 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Transformations.py +62 -0
- python_openhab_rest_client-0.1.1/openhab/tests/UI.py +72 -0
- python_openhab_rest_client-0.1.1/openhab/tests/UUID.py +21 -0
- python_openhab_rest_client-0.1.1/openhab/tests/Voice.py +106 -0
- python_openhab_rest_client-0.1.1/openhab/tests/__init__.py +69 -0
- {python_openhab_rest_client-0.1.0 → python_openhab_rest_client-0.1.1/python_openhab_rest_client.egg-info}/PKG-INFO +1 -1
- python_openhab_rest_client-0.1.1/python_openhab_rest_client.egg-info/SOURCES.txt +106 -0
- {python_openhab_rest_client-0.1.0 → python_openhab_rest_client-0.1.1}/setup.py +1 -1
- python_openhab_rest_client-0.1.1/tests/Actions.py +39 -0
- python_openhab_rest_client-0.1.1/tests/Addons.py +35 -0
- python_openhab_rest_client-0.1.1/tests/Audio.py +18 -0
- python_openhab_rest_client-0.1.1/tests/Auth.py +32 -0
- python_openhab_rest_client-0.1.1/tests/ChannelEvents.py +16 -0
- python_openhab_rest_client-0.1.1/tests/ChannelTypes.py +23 -0
- python_openhab_rest_client-0.1.1/tests/ConfigDescriptions.py +20 -0
- python_openhab_rest_client-0.1.1/tests/Discovery.py +19 -0
- python_openhab_rest_client-0.1.1/tests/Events.py +22 -0
- python_openhab_rest_client-0.1.1/tests/Iconsets.py +18 -0
- python_openhab_rest_client-0.1.1/tests/Inbox.py +26 -0
- python_openhab_rest_client-0.1.1/tests/InboxEvents.py +19 -0
- python_openhab_rest_client-0.1.1/tests/ItemEvents.py +28 -0
- python_openhab_rest_client-0.1.1/tests/Items.py +46 -0
- python_openhab_rest_client-0.1.1/tests/LinkEvents.py +20 -0
- python_openhab_rest_client-0.1.1/tests/Links.py +25 -0
- python_openhab_rest_client-0.1.1/tests/Logging.py +23 -0
- python_openhab_rest_client-0.1.1/tests/ModuleTypes.py +20 -0
- python_openhab_rest_client-0.1.1/tests/Persistence.py +32 -0
- python_openhab_rest_client-0.1.1/tests/ProfileTypes.py +16 -0
- python_openhab_rest_client-0.1.1/tests/Rules.py +35 -0
- python_openhab_rest_client-0.1.1/tests/Services.py +30 -0
- python_openhab_rest_client-0.1.1/tests/Sitemaps.py +25 -0
- python_openhab_rest_client-0.1.1/tests/Systeminfo.py +17 -0
- python_openhab_rest_client-0.1.1/tests/Tags.py +33 -0
- python_openhab_rest_client-0.1.1/tests/Templates.py +20 -0
- python_openhab_rest_client-0.1.1/tests/ThingEvents.py +23 -0
- python_openhab_rest_client-0.1.1/tests/ThingTypes.py +20 -0
- python_openhab_rest_client-0.1.1/tests/Things.py +34 -0
- python_openhab_rest_client-0.1.1/tests/Transformations.py +30 -0
- python_openhab_rest_client-0.1.1/tests/UI.py +45 -0
- python_openhab_rest_client-0.1.1/tests/UUID.py +16 -0
- python_openhab_rest_client-0.1.1/tests/Voice.py +38 -0
- python_openhab_rest_client-0.1.0/openhab/Actions.py +0 -43
- python_openhab_rest_client-0.1.0/openhab/Addons.py +0 -163
- python_openhab_rest_client-0.1.0/openhab/Audio.py +0 -66
- python_openhab_rest_client-0.1.0/openhab/Auth.py +0 -105
- python_openhab_rest_client-0.1.0/openhab/ChannelTypes.py +0 -54
- python_openhab_rest_client-0.1.0/openhab/ConfigDescriptions.py +0 -44
- python_openhab_rest_client-0.1.0/openhab/Discovery.py +0 -28
- python_openhab_rest_client-0.1.0/openhab/Events.py +0 -302
- python_openhab_rest_client-0.1.0/openhab/Iconsets.py +0 -21
- python_openhab_rest_client-0.1.0/openhab/Inbox.py +0 -64
- python_openhab_rest_client-0.1.0/openhab/Items.py +0 -264
- python_openhab_rest_client-0.1.0/openhab/Links.py +0 -98
- python_openhab_rest_client-0.1.0/openhab/Logging.py +0 -55
- python_openhab_rest_client-0.1.0/openhab/ModuleTypes.py +0 -47
- python_openhab_rest_client-0.1.0/openhab/Persistence.py +0 -103
- python_openhab_rest_client-0.1.0/openhab/Rules.py +0 -206
- python_openhab_rest_client-0.1.0/openhab/Services.py +0 -78
- python_openhab_rest_client-0.1.0/openhab/Sitemaps.py +0 -88
- python_openhab_rest_client-0.1.0/openhab/Systeminfo.py +0 -34
- python_openhab_rest_client-0.1.0/openhab/Tags.py +0 -82
- python_openhab_rest_client-0.1.0/openhab/Templates.py +0 -38
- python_openhab_rest_client-0.1.0/openhab/ThingTypes.py +0 -42
- python_openhab_rest_client-0.1.0/openhab/Things.py +0 -199
- python_openhab_rest_client-0.1.0/openhab/Transformations.py +0 -58
- python_openhab_rest_client-0.1.0/openhab/UI.py +0 -75
- python_openhab_rest_client-0.1.0/openhab/UUID.py +0 -18
- python_openhab_rest_client-0.1.0/openhab/Voice.py +0 -147
- python_openhab_rest_client-0.1.0/python_openhab_rest_client.egg-info/SOURCES.txt +0 -73
- python_openhab_rest_client-0.1.0/tests/actions.py +0 -55
- python_openhab_rest_client-0.1.0/tests/addons.py +0 -96
- python_openhab_rest_client-0.1.0/tests/audio.py +0 -16
- python_openhab_rest_client-0.1.0/tests/auth.py +0 -45
- python_openhab_rest_client-0.1.0/tests/channel_events.py +0 -14
- python_openhab_rest_client-0.1.0/tests/channel_types.py +0 -29
- python_openhab_rest_client-0.1.0/tests/config_descriptions.py +0 -23
- python_openhab_rest_client-0.1.0/tests/discovery.py +0 -23
- python_openhab_rest_client-0.1.0/tests/events.py +0 -41
- python_openhab_rest_client-0.1.0/tests/iconsets.py +0 -19
- python_openhab_rest_client-0.1.0/tests/inbox.py +0 -53
- python_openhab_rest_client-0.1.0/tests/inbox_events.py +0 -15
- python_openhab_rest_client-0.1.0/tests/item_events.py +0 -38
- python_openhab_rest_client-0.1.0/tests/items.py +0 -120
- python_openhab_rest_client-0.1.0/tests/link_events.py +0 -14
- python_openhab_rest_client-0.1.0/tests/links.py +0 -74
- python_openhab_rest_client-0.1.0/tests/logging_test.py +0 -43
- python_openhab_rest_client-0.1.0/tests/module_types.py +0 -14
- python_openhab_rest_client-0.1.0/tests/persistence.py +0 -78
- python_openhab_rest_client-0.1.0/tests/profile_types.py +0 -13
- python_openhab_rest_client-0.1.0/tests/rules.py +0 -151
- python_openhab_rest_client-0.1.0/tests/services.py +0 -52
- python_openhab_rest_client-0.1.0/tests/sitemaps.py +0 -65
- python_openhab_rest_client-0.1.0/tests/systeminfo.py +0 -14
- python_openhab_rest_client-0.1.0/tests/tags.py +0 -53
- python_openhab_rest_client-0.1.0/tests/templates.py +0 -28
- python_openhab_rest_client-0.1.0/tests/test.py +0 -11
- python_openhab_rest_client-0.1.0/tests/thing_events.py +0 -17
- python_openhab_rest_client-0.1.0/tests/thing_types.py +0 -28
- python_openhab_rest_client-0.1.0/tests/things.py +0 -75
- python_openhab_rest_client-0.1.0/tests/transformations.py +0 -38
- python_openhab_rest_client-0.1.0/tests/ui.py +0 -70
- python_openhab_rest_client-0.1.0/tests/uuid.py +0 -18
- python_openhab_rest_client-0.1.0/tests/voice.py +0 -119
- {python_openhab_rest_client-0.1.0 → python_openhab_rest_client-0.1.1}/LICENSE +0 -0
- {python_openhab_rest_client-0.1.0 → python_openhab_rest_client-0.1.1}/README.md +0 -0
- {python_openhab_rest_client-0.1.0 → python_openhab_rest_client-0.1.1}/openhab/__init__.py +0 -0
- {python_openhab_rest_client-0.1.0 → python_openhab_rest_client-0.1.1}/python_openhab_rest_client.egg-info/dependency_links.txt +0 -0
- {python_openhab_rest_client-0.1.0 → python_openhab_rest_client-0.1.1}/python_openhab_rest_client.egg-info/requires.txt +0 -0
- {python_openhab_rest_client-0.1.0 → python_openhab_rest_client-0.1.1}/python_openhab_rest_client.egg-info/top_level.txt +0 -0
- {python_openhab_rest_client-0.1.0 → python_openhab_rest_client-0.1.1}/setup.cfg +0 -0
- {python_openhab_rest_client-0.1.0 → python_openhab_rest_client-0.1.1}/tests/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-openhab-rest-client
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: A Python client for the openHAB REST API. This library enables easy interaction with the openHAB REST API to control smart home devices, retrieve status information, and process events.
|
|
5
5
|
Home-page: https://github.com/Michdo93/python-openhab-rest-client
|
|
6
6
|
Author: Michael Christian Dörflinger
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from .Client import OpenHABClient
|
|
2
|
+
import json
|
|
3
|
+
import requests
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Actions:
|
|
7
|
+
def __init__(self, client: OpenHABClient):
|
|
8
|
+
"""
|
|
9
|
+
Initializes the Actions class with an OpenHABClient object.
|
|
10
|
+
|
|
11
|
+
:param client: An instance of OpenHABClient that is used for REST-API communication.
|
|
12
|
+
"""
|
|
13
|
+
self.client = client
|
|
14
|
+
|
|
15
|
+
def getAllActions(self, thingUID: str, language: str = None) -> list:
|
|
16
|
+
"""
|
|
17
|
+
Get all available actions for provided thing UID.
|
|
18
|
+
|
|
19
|
+
:param thingUID: The UID of the thing for which actions are to be retrieved.
|
|
20
|
+
:param language: (Optional) Language setting for the Accept-Language header.
|
|
21
|
+
|
|
22
|
+
:return: A list of actions.
|
|
23
|
+
"""
|
|
24
|
+
header = {"Content-Type": "application/json"}
|
|
25
|
+
if language:
|
|
26
|
+
header["Accept-Language"] = language
|
|
27
|
+
|
|
28
|
+
try:
|
|
29
|
+
response = self.client.get(f"/actions/{thingUID}", header=header)
|
|
30
|
+
|
|
31
|
+
if isinstance(response, dict) and "status" in response:
|
|
32
|
+
status_code = response["status"]
|
|
33
|
+
else:
|
|
34
|
+
return response
|
|
35
|
+
|
|
36
|
+
except requests.exceptions.HTTPError as err:
|
|
37
|
+
status_code = err.response.status_code
|
|
38
|
+
if status_code == 204:
|
|
39
|
+
return {"error": "No actions found."}
|
|
40
|
+
elif status_code == 404:
|
|
41
|
+
return {"error": f"Thing not found: {thingUID}"}
|
|
42
|
+
else:
|
|
43
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
44
|
+
|
|
45
|
+
except requests.exceptions.RequestException as err:
|
|
46
|
+
return {"error": f"Request error: {str(err)}"}
|
|
47
|
+
|
|
48
|
+
if status_code == 200:
|
|
49
|
+
return {"message": "OK"}
|
|
50
|
+
elif status_code == 204:
|
|
51
|
+
return {"error": "No actions found."}
|
|
52
|
+
elif status_code == 404:
|
|
53
|
+
return {"error": f"Thing not found: {thingUID}"}
|
|
54
|
+
|
|
55
|
+
return {"error": f"Unexpected response: {status_code}"}
|
|
56
|
+
|
|
57
|
+
def executeAction(self, thingUID: str, actionUID: str, actionInputs: dict, language: str = None) -> str:
|
|
58
|
+
"""
|
|
59
|
+
Executes a thing action.
|
|
60
|
+
|
|
61
|
+
:param thingUID: The UID of the thing on which the action is to be executed.
|
|
62
|
+
:param actionUID: The UID of the action to be executed.
|
|
63
|
+
:param actionInputs: The inputs for the action as a dictionary.
|
|
64
|
+
:param language: (Optional) Language setting for the Accept-Language header.
|
|
65
|
+
|
|
66
|
+
:return: A response from the server.
|
|
67
|
+
"""
|
|
68
|
+
header = {"Content-Type": "application/json"}
|
|
69
|
+
if language:
|
|
70
|
+
header["Accept-Language"] = language
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
response = self.client.post(
|
|
74
|
+
f"/actions/{thingUID}/{actionUID}", header=header, data=json.dumps(actionInputs))
|
|
75
|
+
|
|
76
|
+
if isinstance(response, dict) and "status" in response:
|
|
77
|
+
status_code = response["status"]
|
|
78
|
+
else:
|
|
79
|
+
return response
|
|
80
|
+
|
|
81
|
+
except requests.exceptions.HTTPError as err:
|
|
82
|
+
status_code = err.response.status_code
|
|
83
|
+
if status_code == 404:
|
|
84
|
+
return {"error": "Action not found."}
|
|
85
|
+
elif status_code == 500:
|
|
86
|
+
return {"error": "Creation of action handler or execution failed."}
|
|
87
|
+
else:
|
|
88
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
89
|
+
|
|
90
|
+
except requests.exceptions.RequestException as err:
|
|
91
|
+
return {"error": f"Request error: {str(err)}"}
|
|
92
|
+
|
|
93
|
+
if status_code == 200:
|
|
94
|
+
return {"message": "OK"}
|
|
95
|
+
elif status_code == 404:
|
|
96
|
+
return {"error": "Action not found."}
|
|
97
|
+
elif status_code == 500:
|
|
98
|
+
return {"error": "Creation of action handler or execution failed."}
|
|
99
|
+
|
|
100
|
+
return {"error": f"Unexpected response: {status_code}"}
|
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from .Client import OpenHABClient
|
|
3
|
+
import urllib.parse
|
|
4
|
+
import requests
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Addons:
|
|
8
|
+
def __init__(self, client: OpenHABClient):
|
|
9
|
+
"""
|
|
10
|
+
Initializes the Addons class with an OpenHABClient instance.
|
|
11
|
+
|
|
12
|
+
:param client: An instance of OpenHABClient used for REST API communication.
|
|
13
|
+
"""
|
|
14
|
+
self.client = client
|
|
15
|
+
|
|
16
|
+
def getAddons(self, serviceID: str = None, language: str = None) -> dict:
|
|
17
|
+
"""
|
|
18
|
+
Retrieves a list of all available add-ons.
|
|
19
|
+
|
|
20
|
+
:param serviceID: Optional service ID to filter the results.
|
|
21
|
+
:param language: Optional language preference for the response.
|
|
22
|
+
|
|
23
|
+
:return: A dictionary containing the add-ons data.
|
|
24
|
+
"""
|
|
25
|
+
params = {"serviceId": serviceID} if serviceID else {}
|
|
26
|
+
header = {"Content-Type": "application/json"}
|
|
27
|
+
if language:
|
|
28
|
+
header["Accept-Language"] = language
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
response = self.client.get("/addons", header=header, params=params)
|
|
32
|
+
|
|
33
|
+
if isinstance(response, dict) and "status" in response:
|
|
34
|
+
status_code = response["status"]
|
|
35
|
+
else:
|
|
36
|
+
return response
|
|
37
|
+
|
|
38
|
+
except requests.exceptions.HTTPError as err:
|
|
39
|
+
status_code = err.response.status_code
|
|
40
|
+
if status_code == 404:
|
|
41
|
+
return {"error": "Service not found."}
|
|
42
|
+
else:
|
|
43
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
44
|
+
|
|
45
|
+
except requests.exceptions.RequestException as err:
|
|
46
|
+
return {"error": f"Request error: {str(err)}"}
|
|
47
|
+
|
|
48
|
+
if status_code == 200:
|
|
49
|
+
return {"message": "OK"}
|
|
50
|
+
elif status_code == 404:
|
|
51
|
+
return {"error": "Service not found."}
|
|
52
|
+
|
|
53
|
+
return {"error": f"Unexpected response: {status_code}"}
|
|
54
|
+
|
|
55
|
+
def getAddon(self, addonID: str, serviceID: str = None, language: str = None) -> dict:
|
|
56
|
+
"""
|
|
57
|
+
Retrieves details of a specific add-on by its ID.
|
|
58
|
+
|
|
59
|
+
:param addonID: The unique identifier of the add-on.
|
|
60
|
+
:param serviceID: Optional service ID to filter the results.
|
|
61
|
+
:param language: Optional language preference for the response.
|
|
62
|
+
|
|
63
|
+
:return: A dictionary containing details of the specified add-on.
|
|
64
|
+
"""
|
|
65
|
+
params = {"serviceId": serviceID} if serviceID else {}
|
|
66
|
+
header = {"Content-Type": "application/json"}
|
|
67
|
+
if language:
|
|
68
|
+
header["Accept-Language"] = language
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
response = self.client.get(
|
|
72
|
+
f"/addons/{addonID}", header=header, params=params)
|
|
73
|
+
|
|
74
|
+
if isinstance(response, dict) and "status" in response:
|
|
75
|
+
status_code = response["status"]
|
|
76
|
+
else:
|
|
77
|
+
return response
|
|
78
|
+
|
|
79
|
+
except requests.exceptions.HTTPError as err:
|
|
80
|
+
status_code = err.response.status_code
|
|
81
|
+
if status_code == 404:
|
|
82
|
+
return {"error": "Not found."}
|
|
83
|
+
else:
|
|
84
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
85
|
+
|
|
86
|
+
except requests.exceptions.RequestException as err:
|
|
87
|
+
return {"error": f"Request error: {str(err)}"}
|
|
88
|
+
|
|
89
|
+
if status_code == 200:
|
|
90
|
+
return {"message": "OK"}
|
|
91
|
+
elif status_code == 404:
|
|
92
|
+
return {"error": "Not found."}
|
|
93
|
+
|
|
94
|
+
return {"error": f"Unexpected response: {status_code}"}
|
|
95
|
+
|
|
96
|
+
def getAddonConfig(self, addonID: str, serviceID: str = None) -> dict:
|
|
97
|
+
"""
|
|
98
|
+
Retrieves the configuration of a specific add-on.
|
|
99
|
+
|
|
100
|
+
:param addonID: The unique identifier of the add-on.
|
|
101
|
+
:param serviceID: Optional service ID to filter the results.
|
|
102
|
+
|
|
103
|
+
:return: A dictionary containing the configuration of the specified add-on.
|
|
104
|
+
"""
|
|
105
|
+
params = {"serviceId": serviceID} if serviceID else {}
|
|
106
|
+
|
|
107
|
+
try:
|
|
108
|
+
response = self.client.get(
|
|
109
|
+
f"/addons/{addonID}/config", header={"Content-Type": "application/json"}, params=params)
|
|
110
|
+
|
|
111
|
+
if isinstance(response, dict) and "status" in response:
|
|
112
|
+
status_code = response["status"]
|
|
113
|
+
else:
|
|
114
|
+
return response
|
|
115
|
+
|
|
116
|
+
except requests.exceptions.HTTPError as err:
|
|
117
|
+
status_code = err.response.status_code
|
|
118
|
+
if status_code == 500:
|
|
119
|
+
return {"error": "Configuration can not be read due to internal error."}
|
|
120
|
+
elif status_code == 404:
|
|
121
|
+
return {"error": "Add-on does not exist."}
|
|
122
|
+
else:
|
|
123
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
124
|
+
|
|
125
|
+
except requests.exceptions.RequestException as err:
|
|
126
|
+
return {"error": f"Request error: {str(err)}"}
|
|
127
|
+
|
|
128
|
+
if status_code == 200:
|
|
129
|
+
return {"message": "OK"}
|
|
130
|
+
elif status_code == 404:
|
|
131
|
+
return {"error": "Add-on does not exist."}
|
|
132
|
+
elif status_code == 500:
|
|
133
|
+
return {"error": "Configuration can not be read due to internal error."}
|
|
134
|
+
|
|
135
|
+
return {"error": f"Unexpected response: {status_code}"}
|
|
136
|
+
|
|
137
|
+
def updateAddonConfig(self, addonID: str, configData: dict, serviceID: str = None) -> dict:
|
|
138
|
+
"""
|
|
139
|
+
Updates the configuration of a specific add-on and returns the updated configuration.
|
|
140
|
+
|
|
141
|
+
:param addonID: The unique identifier of the add-on.
|
|
142
|
+
:param configData: A dictionary containing the new configuration settings.
|
|
143
|
+
:param serviceID: Optional service ID to specify the target service.
|
|
144
|
+
|
|
145
|
+
:return: A dictionary containing the updated configuration.
|
|
146
|
+
"""
|
|
147
|
+
data = {
|
|
148
|
+
**configData} # Create a copy to avoid modifying the original dictionary
|
|
149
|
+
if serviceID:
|
|
150
|
+
data["serviceId"] = serviceID
|
|
151
|
+
|
|
152
|
+
try:
|
|
153
|
+
response = self.client.put(
|
|
154
|
+
f"/addons/{addonID}/config", header={"Content-Type": "application/json"}, data=json.dumps(data))
|
|
155
|
+
|
|
156
|
+
if isinstance(response, dict) and "status" in response:
|
|
157
|
+
status_code = response["status"]
|
|
158
|
+
else:
|
|
159
|
+
return response
|
|
160
|
+
|
|
161
|
+
except requests.exceptions.HTTPError as err:
|
|
162
|
+
status_code = err.response.status_code
|
|
163
|
+
if status_code == 500:
|
|
164
|
+
return {"error": "Configuration can not be updated due to internal error."}
|
|
165
|
+
elif status_code == 404:
|
|
166
|
+
return {"error": "Add-on does not exist."}
|
|
167
|
+
else:
|
|
168
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
169
|
+
|
|
170
|
+
except requests.exceptions.RequestException as err:
|
|
171
|
+
return {"error": f"Request error: {str(err)}"}
|
|
172
|
+
|
|
173
|
+
if status_code == 200:
|
|
174
|
+
return {"message": "OK"}
|
|
175
|
+
elif status_code == 404:
|
|
176
|
+
return {"error": "Add-on does not exist."}
|
|
177
|
+
elif status_code == 500:
|
|
178
|
+
return {"error": "Configuration can not be updated due to internal error."}
|
|
179
|
+
|
|
180
|
+
return {"error": f"Unexpected response: {status_code}"}
|
|
181
|
+
|
|
182
|
+
def installAddon(self, addonID: str, serviceID: str = None, language: str = None) -> dict:
|
|
183
|
+
"""
|
|
184
|
+
Installs an add-on by its ID.
|
|
185
|
+
|
|
186
|
+
:param addonID: The unique identifier of the add-on.
|
|
187
|
+
:param serviceID: Optional service ID to specify the target service.
|
|
188
|
+
:param language: Optional language preference for the response.
|
|
189
|
+
|
|
190
|
+
:return: A dictionary containing the installation status.
|
|
191
|
+
"""
|
|
192
|
+
data = {"serviceId": serviceID} if serviceID else {}
|
|
193
|
+
header = {"Content-Type": "application/json"}
|
|
194
|
+
if language:
|
|
195
|
+
header["Accept-Language"] = language
|
|
196
|
+
|
|
197
|
+
try:
|
|
198
|
+
response = self.client.post(
|
|
199
|
+
f"/addons/{addonID}/install", header=header, data=data)
|
|
200
|
+
|
|
201
|
+
if isinstance(response, dict) and "status" in response:
|
|
202
|
+
status_code = response["status"]
|
|
203
|
+
else:
|
|
204
|
+
return response
|
|
205
|
+
|
|
206
|
+
except requests.exceptions.HTTPError as err:
|
|
207
|
+
status_code = err.response.status_code
|
|
208
|
+
if status_code == 404:
|
|
209
|
+
return {"error": "Not found."}
|
|
210
|
+
else:
|
|
211
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
212
|
+
|
|
213
|
+
except requests.exceptions.RequestException as err:
|
|
214
|
+
return {"error": f"Request error: {str(err)}"}
|
|
215
|
+
|
|
216
|
+
if status_code == 200:
|
|
217
|
+
return {"message": "OK"}
|
|
218
|
+
elif status_code == 404:
|
|
219
|
+
return {"error": "Not found."}
|
|
220
|
+
|
|
221
|
+
return {"error": f"Unexpected response: {status_code}"}
|
|
222
|
+
|
|
223
|
+
def uninstallAddon(self, addonID: str, serviceID: str = None, language: str = None) -> dict:
|
|
224
|
+
"""
|
|
225
|
+
Uninstalls an add-on by its ID.
|
|
226
|
+
|
|
227
|
+
:param addonID: The unique identifier of the add-on.
|
|
228
|
+
:param serviceID: Optional service ID to specify the target service.
|
|
229
|
+
:param language: Optional language preference for the response.
|
|
230
|
+
|
|
231
|
+
:return: A dictionary containing the uninstallation status.
|
|
232
|
+
"""
|
|
233
|
+
data = {"serviceId": serviceID} if serviceID else {}
|
|
234
|
+
header = {"Content-Type": "application/json"}
|
|
235
|
+
if language:
|
|
236
|
+
header["Accept-Language"] = language
|
|
237
|
+
|
|
238
|
+
try:
|
|
239
|
+
response = self.client.post(
|
|
240
|
+
f"/addons/{addonID}/uninstall", header=header, data=data)
|
|
241
|
+
|
|
242
|
+
if isinstance(response, dict) and "status" in response:
|
|
243
|
+
status_code = response["status"]
|
|
244
|
+
else:
|
|
245
|
+
return response
|
|
246
|
+
|
|
247
|
+
except requests.exceptions.HTTPError as err:
|
|
248
|
+
status_code = err.response.status_code
|
|
249
|
+
if status_code == 404:
|
|
250
|
+
return {"error": "Not found."}
|
|
251
|
+
else:
|
|
252
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
253
|
+
|
|
254
|
+
except requests.exceptions.RequestException as err:
|
|
255
|
+
return {"error": f"Request error: {str(err)}"}
|
|
256
|
+
|
|
257
|
+
if status_code == 200:
|
|
258
|
+
return {"message": "OK"}
|
|
259
|
+
elif status_code == 404:
|
|
260
|
+
return {"error": "Not found."}
|
|
261
|
+
|
|
262
|
+
return {"error": f"Unexpected response: {status_code}"}
|
|
263
|
+
|
|
264
|
+
def getAddonServices(self, language: str = None) -> dict:
|
|
265
|
+
"""
|
|
266
|
+
Retrieves a list of all available add-on services.
|
|
267
|
+
|
|
268
|
+
:param language: Optional language preference for the response.
|
|
269
|
+
|
|
270
|
+
:return: A dictionary containing the available add-on services.
|
|
271
|
+
"""
|
|
272
|
+
header = {"Content-Type": "application/json"}
|
|
273
|
+
if language:
|
|
274
|
+
header["Accept-Language"] = language
|
|
275
|
+
|
|
276
|
+
try:
|
|
277
|
+
response = self.client.get(
|
|
278
|
+
"/addons/services", header=header, params=None)
|
|
279
|
+
|
|
280
|
+
if isinstance(response, dict) and "status" in response:
|
|
281
|
+
status_code = response["status"]
|
|
282
|
+
else:
|
|
283
|
+
return response
|
|
284
|
+
|
|
285
|
+
except requests.exceptions.HTTPError as err:
|
|
286
|
+
status_code = err.response.status_code
|
|
287
|
+
if status_code != 200:
|
|
288
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
289
|
+
|
|
290
|
+
except requests.exceptions.RequestException as err:
|
|
291
|
+
return {"error": f"Request error: {str(err)}"}
|
|
292
|
+
|
|
293
|
+
if status_code == 200:
|
|
294
|
+
return {"message": "OK"}
|
|
295
|
+
|
|
296
|
+
return {"error": f"Unexpected response: {status_code}"}
|
|
297
|
+
|
|
298
|
+
def getAddonSuggestions(self, language: str = None) -> dict:
|
|
299
|
+
"""
|
|
300
|
+
Retrieves a list of suggested add-ons for installation.
|
|
301
|
+
|
|
302
|
+
:param language: Optional language preference for the response.
|
|
303
|
+
|
|
304
|
+
:return: A dictionary containing suggested add-ons.
|
|
305
|
+
"""
|
|
306
|
+
header = {"Content-Type": "application/json"}
|
|
307
|
+
if language:
|
|
308
|
+
header["Accept-Language"] = language
|
|
309
|
+
|
|
310
|
+
try:
|
|
311
|
+
response = self.client.get(
|
|
312
|
+
"/addons/suggestions", header=header, params=None)
|
|
313
|
+
|
|
314
|
+
if isinstance(response, dict) and "status" in response:
|
|
315
|
+
status_code = response["status"]
|
|
316
|
+
else:
|
|
317
|
+
return response
|
|
318
|
+
|
|
319
|
+
except requests.exceptions.HTTPError as err:
|
|
320
|
+
status_code = err.response.status_code
|
|
321
|
+
if status_code != 200:
|
|
322
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
323
|
+
|
|
324
|
+
except requests.exceptions.RequestException as err:
|
|
325
|
+
return {"error": f"Request error: {str(err)}"}
|
|
326
|
+
|
|
327
|
+
if status_code == 200:
|
|
328
|
+
return {"message": "OK"}
|
|
329
|
+
|
|
330
|
+
return {"error": f"Unexpected response: {status_code}"}
|
|
331
|
+
|
|
332
|
+
def getAddonTypes(self, language: str = None) -> dict:
|
|
333
|
+
"""
|
|
334
|
+
Retrieves a list of all available add-on types.
|
|
335
|
+
|
|
336
|
+
:param language: Optional language preference for the response.
|
|
337
|
+
|
|
338
|
+
:return: A dictionary containing available add-on types.
|
|
339
|
+
"""
|
|
340
|
+
header = {"Content-Type": "application/json"}
|
|
341
|
+
if language:
|
|
342
|
+
header["Accept-Language"] = language
|
|
343
|
+
|
|
344
|
+
try:
|
|
345
|
+
response = self.client.get(
|
|
346
|
+
"/addons/types", header=header, params=None)
|
|
347
|
+
|
|
348
|
+
if isinstance(response, dict) and "status" in response:
|
|
349
|
+
status_code = response["status"]
|
|
350
|
+
else:
|
|
351
|
+
return response
|
|
352
|
+
|
|
353
|
+
except requests.exceptions.HTTPError as err:
|
|
354
|
+
status_code = err.response.status_code
|
|
355
|
+
if status_code == 404:
|
|
356
|
+
return {"error": "Service not found."}
|
|
357
|
+
else:
|
|
358
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
359
|
+
|
|
360
|
+
except requests.exceptions.RequestException as err:
|
|
361
|
+
return {"error": f"Request error: {str(err)}"}
|
|
362
|
+
|
|
363
|
+
if status_code == 200:
|
|
364
|
+
return {"message": "OK"}
|
|
365
|
+
elif status_code == 404:
|
|
366
|
+
return {"error": "Service not found."}
|
|
367
|
+
|
|
368
|
+
return {"error": f"Unexpected response: {status_code}"}
|
|
369
|
+
|
|
370
|
+
def installAddonFromUrl(self, url: str) -> dict:
|
|
371
|
+
"""
|
|
372
|
+
Installs an add-on from a given URL.
|
|
373
|
+
|
|
374
|
+
:param url: The URL of the add-on to install.
|
|
375
|
+
|
|
376
|
+
:return: A dictionary containing the installation status.
|
|
377
|
+
"""
|
|
378
|
+
encoded_url = urllib.parse.quote(url, safe='') # Encode the URL
|
|
379
|
+
endpoint = f"/addons/url/{encoded_url}/install"
|
|
380
|
+
|
|
381
|
+
try:
|
|
382
|
+
response = self.client.post(
|
|
383
|
+
endpoint, header={"Content-Type": "text/plain"}, data=None)
|
|
384
|
+
|
|
385
|
+
if isinstance(response, dict) and "status" in response:
|
|
386
|
+
status_code = response["status"]
|
|
387
|
+
else:
|
|
388
|
+
return response
|
|
389
|
+
|
|
390
|
+
except requests.exceptions.HTTPError as err:
|
|
391
|
+
status_code = err.response.status_code
|
|
392
|
+
if status_code == 400:
|
|
393
|
+
return {"error": "The given URL is malformed or not valid."}
|
|
394
|
+
else:
|
|
395
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
396
|
+
|
|
397
|
+
except requests.exceptions.RequestException as err:
|
|
398
|
+
return {"error": f"Request error: {str(err)}"}
|
|
399
|
+
|
|
400
|
+
if status_code == 200:
|
|
401
|
+
return {"message": "OK"}
|
|
402
|
+
elif status_code == 400:
|
|
403
|
+
return {"error": "The given URL is malformed or not valid."}
|
|
404
|
+
|
|
405
|
+
return {"error": f"Unexpected response: {status_code}"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
from .Client import OpenHABClient
|
|
2
|
+
import requests
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Audio:
|
|
6
|
+
def __init__(self, client: OpenHABClient):
|
|
7
|
+
"""
|
|
8
|
+
Initializes the Audio class with an OpenHABClient object.
|
|
9
|
+
|
|
10
|
+
:param client: An instance of OpenHABClient used for REST API communication.
|
|
11
|
+
"""
|
|
12
|
+
self.client = client
|
|
13
|
+
|
|
14
|
+
def getDefaultSink(self, language: str = None):
|
|
15
|
+
"""
|
|
16
|
+
Retrieves the default sink if defined, or the first available sink.
|
|
17
|
+
|
|
18
|
+
:param language: (Optional) Language setting for the Accept-Language header.
|
|
19
|
+
|
|
20
|
+
:return: A dictionary containing information about the default sink.
|
|
21
|
+
"""
|
|
22
|
+
header = {"Content-Type": "application/json"}
|
|
23
|
+
if language:
|
|
24
|
+
header["Accept-Language"] = language
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
response = self.client.get("/audio/defaultsink", header=header)
|
|
28
|
+
|
|
29
|
+
if isinstance(response, dict) and "status" in response:
|
|
30
|
+
status_code = response["status"]
|
|
31
|
+
else:
|
|
32
|
+
return response
|
|
33
|
+
|
|
34
|
+
except requests.exceptions.HTTPError as err:
|
|
35
|
+
status_code = err.response.status_code
|
|
36
|
+
if status_code == 404:
|
|
37
|
+
return {"error": "Sink not found."}
|
|
38
|
+
else:
|
|
39
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
40
|
+
|
|
41
|
+
except requests.exceptions.RequestException as err:
|
|
42
|
+
return {"error": f"Request error: {str(err)}"}
|
|
43
|
+
|
|
44
|
+
if status_code == 200:
|
|
45
|
+
return {"message": "OK"}
|
|
46
|
+
elif status_code == 404:
|
|
47
|
+
return {"error": "Sink not found."}
|
|
48
|
+
|
|
49
|
+
return {"error": f"Unexpected response: {status_code}"}
|
|
50
|
+
|
|
51
|
+
def getDefaultSource(self, language: str = None):
|
|
52
|
+
"""
|
|
53
|
+
Retrieves the default source if defined, or the first available source.
|
|
54
|
+
|
|
55
|
+
:param language: (Optional) Language setting for the Accept-Language header.
|
|
56
|
+
|
|
57
|
+
:return: A dictionary containing information about the default source.
|
|
58
|
+
"""
|
|
59
|
+
header = {"Content-Type": "application/json"}
|
|
60
|
+
if language:
|
|
61
|
+
header["Accept-Language"] = language
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
response = self.client.get("/audio/defaultsource", header=header)
|
|
65
|
+
|
|
66
|
+
if isinstance(response, dict) and "status" in response:
|
|
67
|
+
status_code = response["status"]
|
|
68
|
+
else:
|
|
69
|
+
return response
|
|
70
|
+
|
|
71
|
+
except requests.exceptions.HTTPError as err:
|
|
72
|
+
status_code = err.response.status_code
|
|
73
|
+
if status_code == 404:
|
|
74
|
+
return {"error": "Sink not found."}
|
|
75
|
+
else:
|
|
76
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
77
|
+
|
|
78
|
+
except requests.exceptions.RequestException as err:
|
|
79
|
+
return {"error": f"Request error: {str(err)}"}
|
|
80
|
+
|
|
81
|
+
if status_code == 200:
|
|
82
|
+
return {"message": "OK"}
|
|
83
|
+
elif status_code == 404:
|
|
84
|
+
return {"error": "Service not found."}
|
|
85
|
+
|
|
86
|
+
return {"error": f"Unexpected response: {status_code}"}
|
|
87
|
+
|
|
88
|
+
def getSinks(self, language: str = None):
|
|
89
|
+
"""
|
|
90
|
+
Retrieves a list of all available sinks.
|
|
91
|
+
|
|
92
|
+
:param language: (Optional) Language setting for the Accept-Language header.
|
|
93
|
+
|
|
94
|
+
:return: A list of available sinks.
|
|
95
|
+
"""
|
|
96
|
+
header = {"Content-Type": "application/json"}
|
|
97
|
+
if language:
|
|
98
|
+
header["Accept-Language"] = language
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
response = self.client.get("/audio/sinks", header=header)
|
|
102
|
+
|
|
103
|
+
if isinstance(response, dict) and "status" in response:
|
|
104
|
+
status_code = response["status"]
|
|
105
|
+
else:
|
|
106
|
+
return response
|
|
107
|
+
|
|
108
|
+
except requests.exceptions.HTTPError as err:
|
|
109
|
+
status_code = err.response.status_code
|
|
110
|
+
if status_code != 200:
|
|
111
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
112
|
+
|
|
113
|
+
except requests.exceptions.RequestException as err:
|
|
114
|
+
return {"error": f"Request error: {str(err)}"}
|
|
115
|
+
|
|
116
|
+
if status_code == 200:
|
|
117
|
+
return {"message": "OK"}
|
|
118
|
+
|
|
119
|
+
return {"error": f"Unexpected response: {status_code}"}
|
|
120
|
+
|
|
121
|
+
def getSources(self, language: str = None):
|
|
122
|
+
"""
|
|
123
|
+
Retrieves a list of all available sources.
|
|
124
|
+
|
|
125
|
+
:param language: (Optional) Language setting for the Accept-Language header.
|
|
126
|
+
|
|
127
|
+
:return: A list of available sources.
|
|
128
|
+
"""
|
|
129
|
+
header = {"Content-Type": "application/json"}
|
|
130
|
+
if language:
|
|
131
|
+
header["Accept-Language"] = language
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
response = self.client.get("/audio/sources", header=header)
|
|
135
|
+
|
|
136
|
+
if isinstance(response, dict) and "status" in response:
|
|
137
|
+
status_code = response["status"]
|
|
138
|
+
else:
|
|
139
|
+
return response
|
|
140
|
+
|
|
141
|
+
except requests.exceptions.HTTPError as err:
|
|
142
|
+
status_code = err.response.status_code
|
|
143
|
+
if status_code != 200:
|
|
144
|
+
return {"error": f"HTTP error {status_code}: {str(err)}"}
|
|
145
|
+
|
|
146
|
+
except requests.exceptions.RequestException as err:
|
|
147
|
+
return {"error": f"Request error: {str(err)}"}
|
|
148
|
+
|
|
149
|
+
if status_code == 200:
|
|
150
|
+
return {"message": "OK"}
|
|
151
|
+
|
|
152
|
+
return {"error": f"Unexpected response: {status_code}"}
|