python-aidot 0.3.3__tar.gz → 0.3.41__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: python-aidot
3
- Version: 0.3.3
3
+ Version: 0.3.41
4
4
  Summary: aidot control wifi lights
5
5
  Home-page: https://github.com/Aidot-Development-Team/python-aidot
6
6
  Author: aidotdev2024
@@ -1,5 +1,6 @@
1
1
  """The aidot integration."""
2
2
 
3
+ import asyncio
3
4
  import logging
4
5
  import base64
5
6
  import aiohttp
@@ -37,7 +38,7 @@ from .const import (
37
38
  _LOGGER = logging.getLogger(__name__)
38
39
 
39
40
 
40
- def rsa_password_encrypt(message: str):
41
+ def rsa_password_encrypt(message: str) -> str:
41
42
  """Get password rsa encrypt."""
42
43
  public_key = serialization.load_pem_public_key(
43
44
  PUBLIC_KEY_PEM, backend=default_backend()
@@ -60,7 +61,7 @@ class AidotClient:
60
61
  password: str = ""
61
62
  country_name: str = DEFAULT_COUNTRY_NAME
62
63
  login_info: dict[str, Any] = {}
63
- _device_clients: dict[str:DeviceClient]
64
+ _device_clients: dict[str, DeviceClient]
64
65
  _discover: Discover = None
65
66
 
66
67
  def __init__(
@@ -75,7 +76,6 @@ class AidotClient:
75
76
  self.country_name = country_name
76
77
  self.username = username
77
78
  self.password = password
78
- self.login_info = token.copy()
79
79
  self._device_clients = {}
80
80
  for item in SUPPORTED_COUNTRYS:
81
81
  if item["name"] == self.country_name:
@@ -83,21 +83,22 @@ class AidotClient:
83
83
  self._base_url = f"https://prod-{self._region}-api.arnoo.com/v17"
84
84
  break
85
85
  if token is not None:
86
+ self.login_info = token.copy()
86
87
  self.username = token[CONF_USERNAME]
87
88
  self.password = token[CONF_PASSWORD]
88
89
  self._region = token[CONF_REGION]
89
90
  self.country_name = token[CONF_COUNTRY]
90
91
 
91
- def set_token_fresh_cb(self, callback):
92
+ def set_token_fresh_cb(self, callback) -> None:
92
93
  self._token_fresh_cb = callback
93
94
 
94
95
  def get_identifier(self) -> str:
95
96
  return f"{self._region}-{self.username}"
96
97
 
97
- def update_password(self, password: str):
98
+ def update_password(self, password: str) -> None:
98
99
  self.password = password
99
100
 
100
- async def async_post_login(self):
101
+ async def async_post_login(self) -> dict[str, Any]:
101
102
  """Login the user input allows us to connect."""
102
103
  url = f"{self._base_url}/users/loginWithFreeVerification"
103
104
  headers = {CONF_APP_ID: APP_ID, CONF_TERMINAL: "app"}
@@ -126,7 +127,7 @@ class AidotClient:
126
127
  raise AidotUserOrPassIncorrect
127
128
  raise Exception
128
129
 
129
- async def async_refresh_token(self):
130
+ async def async_refresh_token(self) -> dict[str, Any]:
130
131
  url = f"{self._base_url}/users/refreshToken"
131
132
  headers = {CONF_APP_ID: APP_ID, CONF_TERMINAL: "app"}
132
133
  data = {
@@ -150,7 +151,9 @@ class AidotClient:
150
151
  raise AidotAuthFailed
151
152
  return None
152
153
 
153
- async def async_session_get(self, params: str, headers: str | None = None):
154
+ async def async_session_get(
155
+ self, params: str, headers: str | None = None
156
+ ) -> dict[str, Any]:
154
157
  url = f"{self._base_url}{params}"
155
158
  token = self.login_info[CONF_ACCESS_TOKEN]
156
159
  if token is None:
@@ -183,22 +186,22 @@ class AidotClient:
183
186
  raise AidotAuthFailed
184
187
  return aiohttp.ClientError
185
188
 
186
- async def async_get_products(self, product_ids: str):
189
+ async def async_get_products(self, product_ids: str) -> list[dict[str, Any]]:
187
190
  """Get device list."""
188
191
  params = f"/products/{product_ids}"
189
192
  return await self.async_session_get(params)
190
193
 
191
- async def async_get_devices(self, house_id: str):
194
+ async def async_get_devices(self, house_id: str) -> list[dict[str, Any]]:
192
195
  """Get device list."""
193
196
  params = f"/devices?houseId={house_id}"
194
197
  return await self.async_session_get(params)
195
198
 
196
- async def async_get_houses(self):
199
+ async def async_get_houses(self) -> list[dict[str, Any]]:
197
200
  """Get house list."""
198
201
  params = "/houses"
199
202
  return await self.async_session_get(params)
200
203
 
201
- async def async_get_all_device(self):
204
+ async def async_get_all_device(self) -> dict[str, Any]:
202
205
  final_device_list: list[dict[str, Any]] = []
203
206
  try:
204
207
  houses = await self.async_get_houses()
@@ -220,18 +223,19 @@ class AidotClient:
220
223
  raise e
221
224
  return {CONF_DEVICE_LIST: final_device_list}
222
225
 
223
- def get_device_client(self, device: dict[str:Any]) -> DeviceClient:
226
+ def get_device_client(self, device: dict[str, Any]) -> DeviceClient:
224
227
  device_id = device.get(CONF_ID)
225
228
  device_client: DeviceClient = self._device_clients.get(device_id)
226
229
  if device_client is None:
227
230
  device_client = DeviceClient(device, self.login_info)
228
231
  self._device_clients[device_id] = device_client
232
+ asyncio.get_running_loop().create_task(device_client.ping_task())
229
233
  if self._discover is not None:
230
234
  ip = self._discover.discovered_device.get(device_id)
231
235
  device_client.update_ip_address(ip)
232
236
  return device_client
233
237
 
234
- async def start_discover(self) -> None:
238
+ def start_discover(self) -> None:
235
239
  if self._discover is not None:
236
240
  return
237
241
 
@@ -242,7 +246,7 @@ class AidotClient:
242
246
  device_client.update_ip_address(device_ip)
243
247
 
244
248
  self._discover = Discover(self.login_info, _discover_callback)
245
- await self._discover.repeat_broadcast()
249
+ asyncio.get_running_loop().create_task(self._discover.repeat_broadcast())
246
250
 
247
251
  def stop_discover(self) -> None:
248
252
  self._discover.close()
@@ -250,4 +254,6 @@ class AidotClient:
250
254
 
251
255
  def cleanup(self) -> None:
252
256
  self.stop_discover()
257
+ for client in self._device_clients.values():
258
+ asyncio.get_running_loop().create_task(client.close())
253
259
  self._device_clients.clear()
@@ -78,7 +78,7 @@ class DeviceInformation:
78
78
  name: str
79
79
  hw_version: str
80
80
 
81
- def __init__(self, device: dict[str:Any]):
81
+ def __init__(self, device: dict[str, Any]) -> None:
82
82
  self.dev_id = device.get(CONF_ID)
83
83
  self.mac = device.get(CONF_MAC) if device.get(CONF_MAC) is not None else ""
84
84
  self.model_id = device.get(CONF_MODEL_ID)
@@ -114,7 +114,7 @@ class DeviceClient(object):
114
114
  def connecting(self) -> bool:
115
115
  return self._connecting
116
116
 
117
- def __init__(self, device: dict, user_info: dict) -> None:
117
+ def __init__(self, device: dict[str, Any], user_info: dict[str, Any]) -> None:
118
118
  self.ping_count = 0
119
119
  self.status = DeviceStatusData()
120
120
  self.info = DeviceInformation(device)
@@ -131,7 +131,7 @@ class DeviceClient(object):
131
131
  self.device_id = device.get(CONF_ID)
132
132
  self._simpleVersion = device.get("simpleVersion")
133
133
 
134
- async def connect(self, ip_address):
134
+ async def connect(self, ip_address) -> None:
135
135
  self.reader = self.writer = None
136
136
  self._connecting = True
137
137
  try:
@@ -155,7 +155,7 @@ class DeviceClient(object):
155
155
  if self._connecting is not True and self._connect_and_login is not True:
156
156
  await self.connect(self._ip_address)
157
157
 
158
- def getSendPacket(self, message, msgtype):
158
+ def get_send_packet(self, message, msgtype):
159
159
  magic = struct.pack(">H", 0x1EED)
160
160
  _msgtype = struct.pack(">h", msgtype)
161
161
 
@@ -169,7 +169,7 @@ class DeviceClient(object):
169
169
 
170
170
  return packet
171
171
 
172
- async def login(self):
172
+ async def login(self) -> None:
173
173
  login_seq = str(int(time.time() * 1000) + self._login_uuid)[-9:]
174
174
  self._login_uuid += 1
175
175
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
@@ -187,7 +187,7 @@ class DeviceClient(object):
187
187
  },
188
188
  }
189
189
  try:
190
- self.writer.write(self.getSendPacket(json.dumps(message).encode(), 1))
190
+ self.writer.write(self.get_send_packet(json.dumps(message).encode(), 1))
191
191
  await self.writer.drain()
192
192
  data = await self.reader.read(1024)
193
193
  except (BrokenPipeError, ConnectionResetError) as e:
@@ -213,7 +213,7 @@ class DeviceClient(object):
213
213
  self.status.online = True
214
214
  await self.send_action({}, "getDevAttrReq")
215
215
 
216
- async def read_status(self):
216
+ async def read_status(self) -> DeviceStatusData:
217
217
  if self._connect_and_login is False:
218
218
  await asyncio.sleep(2)
219
219
  raise AidotNotLogin
@@ -251,7 +251,7 @@ class DeviceClient(object):
251
251
  self.status.update(payload.get(CONF_ATTR))
252
252
  return self.status
253
253
 
254
- async def ping_task(self):
254
+ async def ping_task(self) -> None:
255
255
  while True:
256
256
  if self._is_close:
257
257
  return
@@ -259,7 +259,7 @@ class DeviceClient(object):
259
259
  await self.send_ping_action()
260
260
  await asyncio.sleep(5)
261
261
 
262
- async def send_dev_attr(self, dev_attr):
262
+ async def send_dev_attr(self, dev_attr) -> None:
263
263
  await self.send_action(dev_attr, "setDevAttrReq")
264
264
 
265
265
  async def async_turn_off(self) -> None:
@@ -279,7 +279,7 @@ class DeviceClient(object):
279
279
  async def async_set_cct(self, cct: int) -> None:
280
280
  await self.send_dev_attr({CONF_CCT: cct})
281
281
 
282
- async def send_action(self, attr, method):
282
+ async def send_action(self, attr, method) -> None:
283
283
  current_timestamp_milliseconds = int(time.time() * 1000)
284
284
  self.seq_num += 1
285
285
  seq = "ha93" + str(self.seq_num).zfill(5)
@@ -321,7 +321,7 @@ class DeviceClient(object):
321
321
  }
322
322
 
323
323
  try:
324
- self.writer.write(self.getSendPacket(json.dumps(action).encode(), 1))
324
+ self.writer.write(self.get_send_packet(json.dumps(action).encode(), 1))
325
325
  await self.writer.drain()
326
326
  except (BrokenPipeError, ConnectionResetError) as e:
327
327
  _LOGGER.error(f"{self.device_id} send action error {e}")
@@ -329,7 +329,7 @@ class DeviceClient(object):
329
329
  except Exception as e:
330
330
  _LOGGER.error(f"{self.device_id} send action error {e}")
331
331
 
332
- async def send_ping_action(self):
332
+ async def send_ping_action(self) -> int:
333
333
  ping = {
334
334
  "service": "test",
335
335
  "method": "pingreq",
@@ -346,7 +346,7 @@ class DeviceClient(object):
346
346
  return -1
347
347
  if self._connect_and_login is False:
348
348
  return -1
349
- self.writer.write(self.getSendPacket(json.dumps(ping).encode(), 2))
349
+ self.writer.write(self.get_send_packet(json.dumps(ping).encode(), 2))
350
350
  await self.writer.drain()
351
351
  self.ping_count += 1
352
352
  return 1
@@ -355,7 +355,7 @@ class DeviceClient(object):
355
355
  await self.reset()
356
356
  return -1
357
357
 
358
- async def reset(self):
358
+ async def reset(self) -> None:
359
359
  try:
360
360
  if self.writer:
361
361
  self.writer.close()
@@ -366,6 +366,7 @@ class DeviceClient(object):
366
366
  self.status.online = False
367
367
  self.ping_count = 0
368
368
 
369
- async def close(self):
369
+ async def close(self) -> None:
370
370
  self._is_close = True
371
371
  await self.reset()
372
+ _LOGGER.info(f"{self.device_id} connect close by user")
@@ -12,10 +12,11 @@ from .exceptions import AidotOSError
12
12
  _LOGGER = logging.getLogger(__name__)
13
13
  _DISCOVER_TIME = 5
14
14
 
15
+
15
16
  class BroadcastProtocol:
16
17
  _is_closed = False
17
18
 
18
- def __init__(self, callback, user_id):
19
+ def __init__(self, callback, user_id) -> None:
19
20
  self.aes_key = bytearray(32)
20
21
  key_string = "T54uednca587"
21
22
  key_bytes = key_string.encode()
@@ -24,7 +25,7 @@ class BroadcastProtocol:
24
25
  self._discover_cb = callback
25
26
  self.user_id = user_id
26
27
 
27
- def connection_made(self, transport):
28
+ def connection_made(self, transport) -> None:
28
29
  self.transport = transport
29
30
  sock = transport.get_extra_info("socket")
30
31
  sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
@@ -54,7 +55,7 @@ class BroadcastProtocol:
54
55
  except Exception as error:
55
56
  _LOGGER.error(f"{self.user_id}:Connection lost due to error: {error}")
56
57
 
57
- def datagram_received(self, data, addr):
58
+ def datagram_received(self, data, addr) -> None:
58
59
  data_str = aes_decrypt(data, self.aes_key)
59
60
  data_json = json.loads(data_str)
60
61
  if "payload" in data_json:
@@ -63,7 +64,7 @@ class BroadcastProtocol:
63
64
  if self._discover_cb:
64
65
  self._discover_cb(devId, {CONF_IPADDRESS: addr[0]})
65
66
 
66
- def error_received(self, exc):
67
+ def error_received(self, exc) -> None:
67
68
  _LOGGER.error(f"{self.user_id}:Error occurred: {exc}")
68
69
 
69
70
  def close(self) -> None:
@@ -72,7 +73,7 @@ class BroadcastProtocol:
72
73
  except Exception as error:
73
74
  _LOGGER.error(f"Connection lost due to error: {error}")
74
75
 
75
- def connection_lost(self, exc):
76
+ def connection_lost(self, exc) -> None:
76
77
  self._is_closed = True
77
78
  if exc:
78
79
  _LOGGER.error(f"{self.user_id}:Connection lost due to error: {exc}")
@@ -81,9 +82,9 @@ class BroadcastProtocol:
81
82
 
82
83
 
83
84
  class Discover:
84
- _login_info: dict[str:Any] = None
85
+ _login_info: dict[str, Any] = None
85
86
  _broadcast_protocol: BroadcastProtocol = None
86
- discovered_device: dict[str:str]
87
+ discovered_device: dict[str, str]
87
88
  _is_close: bool = False
88
89
 
89
90
  def __init__(self, login_info, callback):
@@ -120,7 +121,7 @@ class Discover:
120
121
  if self._is_close is True:
121
122
  return
122
123
 
123
- async def fetch_devices_info(self) -> dict[str:str]:
124
+ async def fetch_devices_info(self) -> dict[str, str]:
124
125
  self.try_create_broadcast()
125
126
  self._broadcast_protocol.send_broadcast()
126
127
  await asyncio.sleep(2)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: python-aidot
3
- Version: 0.3.3
3
+ Version: 0.3.41
4
4
  Summary: aidot control wifi lights
5
5
  Home-page: https://github.com/Aidot-Development-Team/python-aidot
6
6
  Author: aidotdev2024
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="python-aidot",
8
- version="0.3.3",
8
+ version="0.3.41",
9
9
  author="aidotdev2024",
10
10
  url='https://github.com/Aidot-Development-Team/python-aidot',
11
11
  description="aidot control wifi lights",
File without changes
File without changes
File without changes