Skip to content

Commit c4a78f8

Browse files
committed
Move base class out of init and add inheritance
1 parent ea25caf commit c4a78f8

File tree

5 files changed

+150
-181
lines changed

5 files changed

+150
-181
lines changed

pymystrom/__init__.py

Lines changed: 0 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,107 +1 @@
11
"""Base details for the myStrom Python bindings."""
2-
import asyncio
3-
import aiohttp
4-
import async_timeout
5-
from yarl import URL
6-
from typing import Any, Mapping, Optional
7-
import socket
8-
from .exceptions import MyStromConnectionError
9-
10-
import pkg_resources
11-
12-
__version__ = pkg_resources.get_distribution("setuptools").version
13-
14-
TIMEOUT = 10
15-
USER_AGENT = f"PythonMyStrom/{__version__}"
16-
17-
18-
async def _request(
19-
self,
20-
uri: str,
21-
method: str = "GET",
22-
data: Optional[Any] = None,
23-
json_data: Optional[dict] = None,
24-
params: Optional[Mapping[str, str]] = None,
25-
) -> Any:
26-
"""Handle a request to the myStrom device."""
27-
headers = {
28-
"User-Agent": USER_AGENT,
29-
"Accept": "application/json, text/plain, */*",
30-
}
31-
32-
if self._session is None:
33-
self._session = aiohttp.ClientSession()
34-
self._close_session = True
35-
36-
try:
37-
with async_timeout.timeout(TIMEOUT):
38-
response = await self._session.request(
39-
method,
40-
uri,
41-
data=data,
42-
json=json_data,
43-
params=params,
44-
headers=headers,
45-
)
46-
except asyncio.TimeoutError as exception:
47-
raise MyStromConnectionError(
48-
"Timeout occurred while connecting to myStrom device."
49-
) from exception
50-
except (aiohttp.ClientError, socket.gaierror) as exception:
51-
raise MyStromConnectionError(
52-
"Error occurred while communicating with myStrom device."
53-
) from exception
54-
55-
content_type = response.headers.get("Content-Type", "")
56-
if (response.status // 100) in [4, 5]:
57-
response.close()
58-
59-
if "application/json" in content_type:
60-
response_json = await response.json()
61-
return response_json
62-
63-
return response.text
64-
65-
66-
class MyStromDevice:
67-
"""A class for a myStrom device."""
68-
69-
def __init__(
70-
self,
71-
host,
72-
session: aiohttp.client.ClientSession = None,
73-
):
74-
"""Initialize the device."""
75-
self._close_session = False
76-
self._host = host
77-
self._session = session
78-
self.uri = URL.build(scheme="http", host=self._host)
79-
80-
async def get_device_info(self) -> dict:
81-
"""Get the device info of a myStrom device."""
82-
url = URL(self.uri).join(URL("api/v1/info"))
83-
response = await _request(self, uri=url)
84-
if not isinstance(response, dict):
85-
# Fall back to the old API version if the device runs with old firmware
86-
url = URL(self.uri).join(URL("info.json"))
87-
response = await _request(self, uri=url)
88-
return response
89-
90-
async def close(self) -> None:
91-
"""Close an open client session."""
92-
if self._session and self._close_session:
93-
await self._session.close()
94-
95-
async def __aenter__(self) -> "MyStromDevice":
96-
"""Async enter."""
97-
return self
98-
99-
async def __aexit__(self, *exc_info) -> None:
100-
"""Async exit."""
101-
await self.close()
102-
103-
104-
async def get_device_info(host: str) -> dict:
105-
"""Get the device info of a myStrom device."""
106-
async with MyStromDevice(host) as device:
107-
return await device.get_device_info()

pymystrom/bulb.py

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66
from yarl import URL
77
from typing import Any, Dict, Iterable, List, Optional, Union
88

9-
from . import _request as request
9+
from .device import _request as request
10+
from .device import MyStromDevice
1011

1112
_LOGGER = logging.getLogger(__name__)
1213

13-
URI_BULB = URL("api/v1/device")
14+
API_PREFIX = URL("api/v1/device")
1415

1516

16-
class MyStromBulb:
17+
class MyStromBulb(MyStromDevice):
1718
"""A class for a myStrom bulb."""
1819

1920
def __init__(
@@ -23,10 +24,8 @@ def __init__(
2324
session: aiohttp.client.ClientSession = None,
2425
):
2526
"""Initialize the bulb."""
26-
self._close_session = False
27-
self._host = host
27+
super().__init__(host, session)
2828
self._mac = mac
29-
self._session = session
3029
self.brightness = 0
3130
self._color = None
3231
self._consumption = 0
@@ -36,7 +35,7 @@ def __init__(
3635
self._bulb_type = None
3736
self._state = None
3837
self._transition_time = 0
39-
self.uri = URL.build(scheme="http", host=self._host).join(URI_BULB) / self._mac
38+
# self.uri = URL.build(scheme="http", host=self._host).join(URI_BULB) / self._mac
4039

4140
async def get_state(self) -> object:
4241
"""Get the state of the bulb."""
@@ -91,8 +90,9 @@ def state(self) -> Optional[str]:
9190

9291
async def set_on(self):
9392
"""Turn the bulb on with the previous settings."""
93+
url = URL(self.uri).join(URL(f"{API_PREFIX}/{self.mac}"))
9494
response = await request(
95-
self, uri=self.uri, method="POST", data={"action": "on"}
95+
self, url, method="POST", data={"action": "on"}
9696
)
9797
return response
9898

@@ -104,11 +104,12 @@ async def set_color_hex(self, value):
104104
green: 0000FF00
105105
blue: 000000FF
106106
"""
107+
url = URL(self.uri).join(URL(f"{API_PREFIX}/{self.mac}"))
107108
data = {
108109
"action": "on",
109110
"color": value,
110111
}
111-
response = await request(self, uri=self.uri, method="POST", data=data)
112+
response = await request(self, url, method="POST", data=data)
112113
return response
113114

114115
async def set_color_hsv(self, hue, saturation, value):
@@ -120,8 +121,9 @@ async def set_color_hsv(self, hue, saturation, value):
120121
# 'action': 'on',
121122
# 'color': f"{hue};{saturation};{value}",
122123
# }
124+
url = URL(self.uri).join(URL(f"{API_PREFIX}/{self.mac}"))
123125
data = "action=on&color={};{};{}".format(hue, saturation, value)
124-
response = await request(self, uri=self.uri, method="POST", data=data)
126+
response = await request(self, url, method="POST", data=data)
125127
return response
126128

127129
async def set_white(self):
@@ -139,11 +141,12 @@ async def set_sunrise(self, duration):
139141
140142
The brightness is from 0 till 100.
141143
"""
144+
url = URL(self.uri).join(URL(f"{API_PREFIX}/{self.mac}"))
142145
max_brightness = 100
143146
await self.set_transition_time((duration / max_brightness))
144147
for i in range(0, duration):
145148
data = "action=on&color=3;{}".format(i)
146-
await request(self, uri=self.uri, method="POST", data=data)
149+
await request(self, url, method="POST", data=data)
147150
await asyncio.sleep(duration / max_brightness)
148151

149152
async def set_flashing(self, duration, hsv1, hsv2):
@@ -157,27 +160,19 @@ async def set_flashing(self, duration, hsv1, hsv2):
157160

158161
async def set_transition_time(self, value):
159162
"""Set the transition time in ms."""
163+
url = URL(self.uri).join(URL(f"{API_PREFIX}/{self.mac}"))
160164
response = await request(
161-
self, uri=self.uri, method="POST", data={"ramp": int(round(value))}
165+
self, url, method="POST", data={"ramp": int(round(value))}
162166
)
163167
return response
164168

165169
async def set_off(self):
166170
"""Turn the bulb off."""
171+
url = URL(self.uri).join(URL(f"{API_PREFIX}/{self.mac}"))
167172
response = await request(
168-
self, uri=self.uri, method="POST", data={"action": "off"}
173+
self, url, method="POST", data={"action": "off"}
169174
)
170175
return response
171176

172-
async def close(self) -> None:
173-
"""Close an open client session."""
174-
if self._session and self._close_session:
175-
await self._session.close()
176-
177177
async def __aenter__(self) -> "MyStromBulb":
178-
"""Async enter."""
179-
return self
180-
181-
async def __aexit__(self, *exc_info) -> None:
182-
"""Async exit."""
183-
await self.close()
178+
super().__aenter__()

pymystrom/device.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
"""Base device class for all myStrom devices."""
2+
from typing import Any, Mapping, Optional
3+
import asyncio
4+
import aiohttp
5+
import pkg_resources
6+
import socket
7+
import async_timeout
8+
from yarl import URL
9+
from .exceptions import MyStromConnectionError
10+
11+
__version__ = pkg_resources.get_distribution("setuptools").version
12+
13+
TIMEOUT = 10
14+
USER_AGENT = f"PythonMyStrom/{__version__}"
15+
16+
17+
async def _request(
18+
self,
19+
uri: str,
20+
method: str = "GET",
21+
data: Optional[Any] = None,
22+
json_data: Optional[dict] = None,
23+
params: Optional[Mapping[str, str]] = None,
24+
) -> Any:
25+
"""Handle a request to the myStrom device."""
26+
headers = {
27+
"User-Agent": USER_AGENT,
28+
"Accept": "application/json, text/plain, */*",
29+
}
30+
31+
if self._session is None:
32+
self._session = aiohttp.ClientSession()
33+
self._close_session = True
34+
35+
try:
36+
with async_timeout.timeout(TIMEOUT):
37+
response = await self._session.request(
38+
method,
39+
uri,
40+
data=data,
41+
json=json_data,
42+
params=params,
43+
headers=headers,
44+
)
45+
except asyncio.TimeoutError as exception:
46+
raise MyStromConnectionError(
47+
"Timeout occurred while connecting to myStrom device."
48+
) from exception
49+
except (aiohttp.ClientError, socket.gaierror) as exception:
50+
raise MyStromConnectionError(
51+
"Error occurred while communicating with myStrom device."
52+
) from exception
53+
54+
content_type = response.headers.get("Content-Type", "")
55+
if (response.status // 100) in [4, 5]:
56+
response.close()
57+
58+
if "application/json" in content_type:
59+
response_json = await response.json()
60+
return response_json
61+
62+
return response.text
63+
64+
class MyStromDevice:
65+
"""A class for a myStrom device."""
66+
67+
def __init__(
68+
self,
69+
host,
70+
session: aiohttp.client.ClientSession = None,
71+
):
72+
"""Initialize the device."""
73+
self._close_session = False
74+
self._host = host
75+
self._session = session
76+
self.uri = URL.build(scheme="http", host=self._host)
77+
78+
async def get_device_info(self) -> dict:
79+
"""Get the device info of a myStrom device."""
80+
url = URL(self.uri).join(URL("api/v1/info"))
81+
print(url)
82+
response = await _request(self, uri=url)
83+
if not isinstance(response, dict):
84+
# Fall back to the old API version if the device runs with old firmware
85+
url = URL(self.uri).join(URL("info.json"))
86+
response = await _request(self, uri=url)
87+
return response
88+
89+
async def close(self) -> None:
90+
"""Close an open client session."""
91+
if self._session and self._close_session:
92+
await self._session.close()
93+
94+
async def __aenter__(self) -> "MyStromDevice":
95+
"""Async enter."""
96+
return self
97+
98+
async def __aexit__(self, *exc_info) -> None:
99+
"""Async exit."""
100+
await self.close()
101+
102+
103+
async def get_device_info(host: str) -> dict:
104+
"""Get the device info of a myStrom device."""
105+
async with MyStromDevice(host) as device:
106+
return await device.get_device_info()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy