python-swidget 1.2.2__py3-none-any.whl → 1.2.4__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.
swidget/swidgetdimmer.py CHANGED
@@ -1,18 +1,30 @@
1
+ """Module for SwidgetDimmer."""
1
2
  import logging
2
3
 
3
- from swidget.swidgetdevice import (
4
- DeviceType,
5
- SwidgetDevice
6
- )
7
4
  from swidget.exceptions import SwidgetException
5
+ from swidget.swidgetdevice import DeviceType, SwidgetDevice
8
6
 
9
7
  _LOGGER = logging.getLogger(__name__)
10
8
 
11
9
 
12
10
  class SwidgetDimmer(SwidgetDevice):
11
+ """Representation of a Swidget Dimmer device."""
13
12
 
14
- def __init__(self, host, token_name: str, secret_key: str, use_https: bool, use_websockets: bool) -> None:
15
- super().__init__(host=host, token_name=token_name, secret_key=secret_key, use_https=use_https, use_websockets=use_websockets)
13
+ def __init__(
14
+ self,
15
+ host,
16
+ token_name: str,
17
+ secret_key: str,
18
+ use_https: bool,
19
+ use_websockets: bool,
20
+ ) -> None:
21
+ super().__init__(
22
+ host=host,
23
+ token_name=token_name,
24
+ secret_key=secret_key,
25
+ use_https=use_https,
26
+ use_websockets=use_websockets,
27
+ )
16
28
  self._device_type = DeviceType.Dimmer
17
29
 
18
30
  @property # type: ignore
@@ -25,26 +37,37 @@ class SwidgetDimmer(SwidgetDevice):
25
37
  if not self.is_dimmable:
26
38
  raise SwidgetException("Device is not dimmable.")
27
39
  try:
28
- return self.assemblies['host'].components["0"].functions["level"]["now"]
40
+ return self.assemblies["host"].components["0"].functions["level"]["now"]
29
41
  except KeyError:
30
- return self.assemblies['host'].components["0"].functions["level"]["default"]
42
+ return self.assemblies["host"].components["0"].functions["level"]["default"]
31
43
 
32
44
  async def set_brightness(self, brightness) -> None:
33
45
  """Set the brightness of the device."""
34
- _LOGGER.debug("SwidgetDimmer.set_brightness() called with brightness: {brightness}")
35
- self.assemblies['host'].components["0"].functions["level"]["now"] = brightness
46
+ _LOGGER.debug(
47
+ "SwidgetDimmer.set_brightness() called with brightness: {brightness}"
48
+ )
49
+ self.assemblies["host"].components["0"].functions["level"]["now"] = brightness
36
50
  await self.send_command(
37
- assembly="host", component="0", function="level", command={"now": brightness}
51
+ assembly="host",
52
+ component="0",
53
+ function="level",
54
+ command={"now": brightness},
38
55
  )
39
56
 
40
57
  async def set_default_brightness(self, brightness) -> None:
41
- _LOGGER.debug("SwidgetDimmer.set_default_brightness() called with brightness: {brightness}")
58
+ """Set the brightness of the device when it is turned on."""
59
+ _LOGGER.debug(
60
+ "SwidgetDimmer.set_default_brightness() called with brightness: {brightness}"
61
+ )
42
62
  await self.send_command(
43
- assembly="host", component="0", function="level", command={"default": brightness}
63
+ assembly="host",
64
+ component="0",
65
+ function="level",
66
+ command={"default": brightness},
44
67
  )
45
68
 
46
69
  @property # type: ignore
47
70
  def is_dimmable(self) -> bool:
48
71
  """Whether the switch supports brightness changes."""
49
72
  _LOGGER.debug("SwidgetDimmer.is_dimmable() called")
50
- return True
73
+ return True
swidget/swidgetoutlet.py CHANGED
@@ -1,11 +1,23 @@
1
- from swidget.swidgetdevice import (
2
- DeviceType,
3
- SwidgetDevice
4
- )
1
+ """Module for SwidgetOutlet."""
2
+ from swidget.swidgetdevice import DeviceType, SwidgetDevice
5
3
 
6
4
 
7
5
  class SwidgetOutlet(SwidgetDevice):
6
+ """Representation of a Swidget Outlet device."""
8
7
 
9
- def __init__(self, host, token_name: str, secret_key: str, use_https: bool, use_websockets: bool) -> None:
10
- super().__init__(host=host, token_name=token_name, secret_key=secret_key, use_https=use_https, use_websockets=use_websockets)
11
- self._device_type = DeviceType.Outlet
8
+ def __init__(
9
+ self,
10
+ host,
11
+ token_name: str,
12
+ secret_key: str,
13
+ use_https: bool,
14
+ use_websockets: bool,
15
+ ) -> None:
16
+ super().__init__(
17
+ host=host,
18
+ token_name=token_name,
19
+ secret_key=secret_key,
20
+ use_https=use_https,
21
+ use_websockets=use_websockets,
22
+ )
23
+ self._device_type = DeviceType.Outlet
swidget/swidgetswitch.py CHANGED
@@ -1,11 +1,23 @@
1
- from swidget.swidgetdevice import (
2
- DeviceType,
3
- SwidgetDevice
4
- )
1
+ """Module for a generic SwidgetSwitch."""
2
+ from swidget.swidgetdevice import DeviceType, SwidgetDevice
5
3
 
6
4
 
7
5
  class SwidgetSwitch(SwidgetDevice):
6
+ """Representation of a Swidget Switch device."""
8
7
 
9
- def __init__(self, host, token_name: str, secret_key: str, use_https: bool, use_websockets: bool) -> None:
10
- super().__init__(host=host, token_name=token_name, secret_key=secret_key, use_https=use_https, use_websockets=use_websockets)
11
- self._device_type = DeviceType.Switch
8
+ def __init__(
9
+ self,
10
+ host,
11
+ token_name: str,
12
+ secret_key: str,
13
+ use_https: bool,
14
+ use_websockets: bool,
15
+ ) -> None:
16
+ super().__init__(
17
+ host=host,
18
+ token_name=token_name,
19
+ secret_key=secret_key,
20
+ use_https=use_https,
21
+ use_websockets=use_websockets,
22
+ )
23
+ self._device_type = DeviceType.Switch
@@ -1,23 +1,39 @@
1
+ """Module for SwidgetTimerSwitch."""
1
2
  import logging
2
3
  from typing import Any
3
4
 
4
- from swidget.swidgetdevice import (
5
- DeviceType,
6
- )
5
+ from swidget.swidgetdevice import DeviceType
7
6
  from swidget.swidgetswitch import SwidgetSwitch
8
7
 
9
8
  _LOGGER = logging.getLogger(__name__)
10
9
 
11
10
 
12
11
  class SwidgetTimerSwitch(SwidgetSwitch):
12
+ """Class to represent a Swidget Timer Switch (also known as a 20/40/60 switch)."""
13
13
 
14
- def __init__(self, host, token_name: str, secret_key: str, use_https: bool, use_websockets: bool) -> None:
15
- super().__init__(host=host, token_name=token_name, secret_key=secret_key, use_https=use_https, use_websockets=use_websockets)
14
+ def __init__(
15
+ self,
16
+ host,
17
+ token_name: str,
18
+ secret_key: str,
19
+ use_https: bool,
20
+ use_websockets: bool,
21
+ ) -> None:
22
+ super().__init__(
23
+ host=host,
24
+ token_name=token_name,
25
+ secret_key=secret_key,
26
+ use_https=use_https,
27
+ use_websockets=use_websockets,
28
+ )
16
29
  self._device_type = DeviceType.TimerSwitch
17
30
 
18
31
  async def set_countdown_timer(self, minutes) -> Any:
19
32
  """Set the countdown timer."""
20
33
  _LOGGER.debug("SwidgetTimerSwitch.set_brightness() called")
21
34
  await self.send_command(
22
- assembly="host", component="0", function="timer", command={"duration": minutes}
23
- )
35
+ assembly="host",
36
+ component="0",
37
+ function="timer",
38
+ command={"duration": minutes},
39
+ )
swidget/websocket.py CHANGED
@@ -1,10 +1,12 @@
1
+ """Module to handle websocket connections to Swidget devices."""
1
2
  import asyncio
2
- import aiohttp
3
- from aiohttp import ClientWebSocketResponse, WSMsgType
4
3
  import logging
5
4
  import socket
6
5
  from typing import Any
7
6
 
7
+ import aiohttp
8
+ from aiohttp import ClientWebSocketResponse, WSMsgType
9
+
8
10
  _LOGGER = logging.getLogger(__name__)
9
11
 
10
12
 
@@ -20,7 +22,7 @@ async def cancel_task(*tasks: asyncio.Task | None) -> None:
20
22
 
21
23
 
22
24
  class SwidgetWebsocket:
23
- """A websocket connection to a Swidget Device"""
25
+ """A websocket connection to a Swidget Device."""
24
26
 
25
27
  # pylint: disable=too-many-instance-attributes
26
28
  _client: aiohttp.ClientWebSocketResponse | None = None
@@ -43,11 +45,12 @@ class SwidgetWebsocket:
43
45
  self._state = None
44
46
  self.failed_attempts = 0
45
47
  self._error_reason = None
46
- self.headers = {'Connection': 'Upgrade'}
48
+ self.headers = {"Connection": "Upgrade"}
47
49
  self._receiver_task: asyncio.Task | None = None
48
50
 
49
51
  @property
50
52
  def connected(self) -> bool:
53
+ """Return of status of whether the device is currently connected."""
51
54
  return self._client is not None and not self._client.closed
52
55
 
53
56
  @property
@@ -56,15 +59,15 @@ class SwidgetWebsocket:
56
59
  return self._client
57
60
 
58
61
  def get_uri(self, host, token_name, secret_key):
59
- """Generate the websocket URI"""
62
+ """Generate the websocket URI."""
60
63
  if self.use_security:
61
64
  return f"wss://{host}/api/v1/sock?{token_name}={secret_key}"
62
65
  else:
63
66
  return f"ws://{host}/api/v1/sock?{token_name}={secret_key}"
64
67
 
65
68
  async def connect(self) -> None:
66
- _LOGGER.debug("websocket.connect() called")
67
69
  """Create a new connection and, optionally, start the monitor."""
70
+ _LOGGER.debug("websocket.connect() called")
68
71
  await cancel_task(self._receiver_task)
69
72
  if self.connected:
70
73
  _LOGGER.debug("Websocket already connected")
@@ -78,13 +81,22 @@ class SwidgetWebsocket:
78
81
 
79
82
  try:
80
83
  _LOGGER.debug("Trying to connect")
81
- self._client = await self.session.ws_connect(url=self.uri, headers=self.headers, verify_ssl=self._verify_ssl, heartbeat=30)
84
+ self._client = await self.session.ws_connect(
85
+ url=self.uri,
86
+ headers=self.headers,
87
+ verify_ssl=self._verify_ssl,
88
+ heartbeat=30,
89
+ )
82
90
  _LOGGER.debug("Websocket now connected")
83
91
  except aiohttp.WSServerHandshakeError as handshake_error:
84
- _LOGGER.error(f"Error occurred during websocket handshake: {handshake_error}")
92
+ _LOGGER.error(
93
+ f"Error occurred during websocket handshake: {handshake_error}"
94
+ )
85
95
  raise
86
96
  except aiohttp.ClientConnectionError as connection_error:
87
- _LOGGER.error(f"Error connecting to the websocket server: {connection_error}")
97
+ _LOGGER.error(
98
+ f"Error connecting to the websocket server: {connection_error}"
99
+ )
88
100
  raise
89
101
  except socket.gaierror as gai_error:
90
102
  _LOGGER.error(f"Error resolving host: {gai_error}")
@@ -95,12 +107,14 @@ class SwidgetWebsocket:
95
107
  self._receiver_task = asyncio.ensure_future(self.listen())
96
108
 
97
109
  async def close(self) -> None:
110
+ """Close the websocket."""
98
111
  _LOGGER.debug("websocket.close() called")
99
112
  if self._client is not None and not self._client.closed:
100
113
  await self._client.close()
101
114
  self._client = None
102
115
 
103
116
  async def disconnect(self) -> None:
117
+ """Wrapper of the close() function."""
104
118
  await self.close()
105
119
 
106
120
  async def send_str(self, message):
@@ -110,18 +124,24 @@ class SwidgetWebsocket:
110
124
  raise ConnectionError
111
125
  message = str(message)
112
126
  _LOGGER.debug(f"Sending messsage over websocket: {message}")
113
- await self._client.send_str(f'{message}')
127
+ await self._client.send_str(f"{message}")
114
128
 
115
129
  async def listen(self):
130
+ """Ask the client to listen to websocket events."""
116
131
  _LOGGER.debug("websocket.listen() called")
132
+ # Check if the websocket is connected
117
133
  if not self._client or not self.connected:
118
- raise
134
+ _LOGGER.error("Websocket is not connected")
135
+ raise ConnectionError("Websocket is not connected")
119
136
 
120
137
  while not self._client.closed:
121
- message = await self._client.receive()
138
+ try:
139
+ message = await self._client.receive()
140
+ except StopAsyncIteration:
141
+ break
122
142
 
123
143
  if message.type == aiohttp.WSMsgType.ERROR:
124
- raise
144
+ raise ConnectionError("Websocket error occurred")
125
145
 
126
146
  if message.type == aiohttp.WSMsgType.TEXT:
127
147
  message_data = message.json()
@@ -133,7 +153,10 @@ class SwidgetWebsocket:
133
153
  aiohttp.WSMsgType.CLOSED,
134
154
  aiohttp.WSMsgType.CLOSING,
135
155
  ):
136
- _LOGGER.error("Connection to the Swidget WebSocket on has been closed")
156
+ _LOGGER.error("Connection to the Swidget WebSocket has been closed")
157
+ break
158
+
159
+ self._client = None # Ensure client is set to None when closed
137
160
 
138
161
  async def receive_message_or_raise(self) -> Any:
139
162
  """Receive ONE (raw) message or raise."""
@@ -147,9 +170,7 @@ class SwidgetWebsocket:
147
170
  raise ConnectionError
148
171
 
149
172
  if ws_msg.type != WSMsgType.TEXT:
150
- raise ValueError(
151
- f"Received non-Text message: {ws_msg.type}: {ws_msg.data}"
152
- )
173
+ raise ValueError(f"Received non-Text message: {ws_msg.type}: {ws_msg.data}")
153
174
 
154
175
  try:
155
176
  msg = ws_msg.json()
@@ -164,4 +185,4 @@ class SwidgetWebsocket:
164
185
  def __repr__(self) -> str:
165
186
  """Return the representation."""
166
187
  prefix = "" if self.connected else "not "
167
- return f"{type(self).__name__}(ws_server_url={self.host}, {prefix}connected)"
188
+ return f"{type(self).__name__}(ws_server_url={self.host}, {prefix}connected)"
@@ -1,16 +0,0 @@
1
- swidget/__init__.py,sha256=sUaN7mSvEe40HDHjtEiqUtUGdb3239XbFLb14PnOpHw,1330
2
- swidget/cli.py,sha256=G61GQijygVL1W59EQVVk3dA7SOikWhZsZ5iy33cB5FQ,8951
3
- swidget/discovery.py,sha256=b5-C75d0qNl3-PGK6vq5i02uTFaRlQq_yc6l_qG4FmM,3865
4
- swidget/exceptions.py,sha256=JOSwaOwwv8YLry687vZmTQLY-BrrTpCs0CIZr7u-J48,79
5
- swidget/provision.py,sha256=Mw_0lHUj584F6fg2H80WVOd3Iz57C300hDnNDi1TSIw,4591
6
- swidget/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- swidget/swidgetdevice.py,sha256=HdRyiQ3S0X8Dxq3p07Ksbbk5Xer39pVWPtPSPnf9ex8,21853
8
- swidget/swidgetdimmer.py,sha256=doPajuRoSSI0aU3WlT-t_WZyxsRyxAB-uMiXYz-YP88,1969
9
- swidget/swidgetoutlet.py,sha256=XUz42SV3_CaNp0gOGtBa1rAqG5xpmGpdLMem-OHCMM4,402
10
- swidget/swidgetswitch.py,sha256=VorjxnV42wWmu77CmWaasrMOAFIO15tQReRyaN7D-qU,402
11
- swidget/swidgettimerswitch.py,sha256=7-F81U7VWi-YCW6vYyOcZyKjttHCuW_P5LLbtLmdzfk,820
12
- swidget/websocket.py,sha256=27wCxJNmOAK1ba8lLQ3kxXEgg6Cp30Uri6P5OpaWV00,5768
13
- python_swidget-1.2.2.dist-info/METADATA,sha256=vbkdFQ4SWOjMgYuZi3Gne1uiiezeuNg55hjc-Q1379Q,1853
14
- python_swidget-1.2.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
15
- python_swidget-1.2.2.dist-info/entry_points.txt,sha256=ksGZuoFNqyktLnxPUCFDHokC_7n1uu4GSMUEerwwDmY,43
16
- python_swidget-1.2.2.dist-info/RECORD,,