python-roborock 2.29.0__tar.gz → 2.29.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_roborock-2.29.0 → python_roborock-2.29.1}/PKG-INFO +1 -1
- {python_roborock-2.29.0 → python_roborock-2.29.1}/pyproject.toml +1 -1
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/containers.py +45 -77
- {python_roborock-2.29.0 → python_roborock-2.29.1}/LICENSE +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/README.md +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/__init__.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/api.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/cli.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/cloud_api.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/code_mappings.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/command_cache.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/const.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/device_features.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/devices/README.md +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/devices/__init__.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/devices/a01_channel.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/devices/channel.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/devices/device.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/devices/device_manager.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/devices/local_channel.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/devices/mqtt_channel.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/devices/traits/dyad.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/devices/traits/status.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/devices/traits/trait.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/devices/traits/zeo.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/devices/v1_channel.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/devices/v1_rpc_channel.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/exceptions.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/local_api.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/mqtt/__init__.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/mqtt/roborock_session.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/mqtt/session.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/protocol.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/protocols/a01_protocol.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/protocols/v1_protocol.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/py.typed +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/roborock_future.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/roborock_message.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/roborock_typing.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/util.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/version_1_apis/__init__.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/version_1_apis/roborock_client_v1.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/version_1_apis/roborock_local_client_v1.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/version_1_apis/roborock_mqtt_client_v1.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/version_a01_apis/__init__.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/version_a01_apis/roborock_client_a01.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/version_a01_apis/roborock_mqtt_client_a01.py +0 -0
- {python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/web_api.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import dataclasses
|
|
3
2
|
import datetime
|
|
4
3
|
import json
|
|
5
4
|
import logging
|
|
6
5
|
import re
|
|
6
|
+
import types
|
|
7
7
|
from dataclasses import asdict, dataclass, field
|
|
8
8
|
from datetime import timezone
|
|
9
9
|
from enum import Enum
|
|
@@ -95,105 +95,73 @@ from .exceptions import RoborockException
|
|
|
95
95
|
_LOGGER = logging.getLogger(__name__)
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
def
|
|
98
|
+
def _camelize(s: str):
|
|
99
99
|
first, *others = s.split("_")
|
|
100
100
|
if len(others) == 0:
|
|
101
101
|
return s
|
|
102
102
|
return "".join([first.lower(), *map(str.title, others)])
|
|
103
103
|
|
|
104
104
|
|
|
105
|
-
def
|
|
105
|
+
def _decamelize(s: str):
|
|
106
106
|
return re.sub("([A-Z]+)", "_\\1", s).lower()
|
|
107
107
|
|
|
108
108
|
|
|
109
|
-
def decamelize_obj(d: dict | list, ignore_keys: list[str]):
|
|
110
|
-
if isinstance(d, RoborockBase):
|
|
111
|
-
d = d.as_dict()
|
|
112
|
-
if isinstance(d, list):
|
|
113
|
-
return [decamelize_obj(i, ignore_keys) if isinstance(i, dict | list) else i for i in d]
|
|
114
|
-
return {
|
|
115
|
-
(decamelize(a) if a not in ignore_keys else a): decamelize_obj(b, ignore_keys)
|
|
116
|
-
if isinstance(b, dict | list)
|
|
117
|
-
else b
|
|
118
|
-
for a, b in d.items()
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
|
|
122
109
|
@dataclass
|
|
123
110
|
class RoborockBase:
|
|
124
111
|
_ignore_keys = [] # type: ignore
|
|
125
|
-
is_cached = False
|
|
126
112
|
|
|
127
113
|
@staticmethod
|
|
128
|
-
def
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return_list.append(cls_type(**obj))
|
|
141
|
-
return return_list
|
|
142
|
-
if issubclass(class_type, RoborockBase):
|
|
143
|
-
converted_value = class_type.from_dict(value)
|
|
144
|
-
else:
|
|
145
|
-
converted_value = class_type(value)
|
|
146
|
-
return converted_value
|
|
147
|
-
except NameError as err:
|
|
148
|
-
_LOGGER.exception(err)
|
|
149
|
-
except ValueError as err:
|
|
150
|
-
_LOGGER.exception(err)
|
|
151
|
-
except Exception as err:
|
|
152
|
-
_LOGGER.exception(err)
|
|
153
|
-
raise Exception("Fail")
|
|
114
|
+
def _convert_to_class_obj(class_type: type, value):
|
|
115
|
+
if get_origin(class_type) is list:
|
|
116
|
+
sub_type = get_args(class_type)[0]
|
|
117
|
+
return [RoborockBase._convert_to_class_obj(sub_type, obj) for obj in value]
|
|
118
|
+
if get_origin(class_type) is dict:
|
|
119
|
+
_, value_type = get_args(class_type) # assume keys are only basic types
|
|
120
|
+
return {k: RoborockBase._convert_to_class_obj(value_type, v) for k, v in value.items()}
|
|
121
|
+
if issubclass(class_type, RoborockBase):
|
|
122
|
+
return class_type.from_dict(value)
|
|
123
|
+
if class_type is Any:
|
|
124
|
+
return value
|
|
125
|
+
return class_type(value) # type: ignore[call-arg]
|
|
154
126
|
|
|
155
127
|
@classmethod
|
|
156
128
|
def from_dict(cls, data: dict[str, Any]):
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
# It's a union
|
|
174
|
-
types = field_type.split("|")
|
|
175
|
-
for type in types:
|
|
176
|
-
if "None" in type or "Any" in type:
|
|
177
|
-
continue
|
|
178
|
-
try:
|
|
179
|
-
data[key] = RoborockBase.convert_to_class_obj(type, value)
|
|
180
|
-
break
|
|
181
|
-
except Exception:
|
|
182
|
-
...
|
|
183
|
-
else:
|
|
129
|
+
"""Create an instance of the class from a dictionary."""
|
|
130
|
+
if not isinstance(data, dict):
|
|
131
|
+
return None
|
|
132
|
+
field_types = {field.name: field.type for field in dataclasses.fields(cls)}
|
|
133
|
+
result: dict[str, Any] = {}
|
|
134
|
+
for key, value in data.items():
|
|
135
|
+
key = _decamelize(key)
|
|
136
|
+
if (field_type := field_types.get(key)) is None:
|
|
137
|
+
continue
|
|
138
|
+
if value == "None" or value is None:
|
|
139
|
+
result[key] = None
|
|
140
|
+
continue
|
|
141
|
+
if isinstance(field_type, types.UnionType):
|
|
142
|
+
for subtype in get_args(field_type):
|
|
143
|
+
if subtype is types.NoneType:
|
|
144
|
+
continue
|
|
184
145
|
try:
|
|
185
|
-
|
|
146
|
+
result[key] = RoborockBase._convert_to_class_obj(subtype, value)
|
|
147
|
+
break
|
|
186
148
|
except Exception:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
149
|
+
_LOGGER.exception(f"Failed to convert {key} with value {value} to type {subtype}")
|
|
150
|
+
continue
|
|
151
|
+
else:
|
|
152
|
+
try:
|
|
153
|
+
result[key] = RoborockBase._convert_to_class_obj(field_type, value)
|
|
154
|
+
except Exception:
|
|
155
|
+
_LOGGER.exception(f"Failed to convert {key} with value {value} to type {field_type}")
|
|
156
|
+
continue
|
|
157
|
+
|
|
158
|
+
return cls(**result)
|
|
191
159
|
|
|
192
160
|
def as_dict(self) -> dict:
|
|
193
161
|
return asdict(
|
|
194
162
|
self,
|
|
195
163
|
dict_factory=lambda _fields: {
|
|
196
|
-
|
|
164
|
+
_camelize(key): value.value if isinstance(value, Enum) else value
|
|
197
165
|
for (key, value) in _fields
|
|
198
166
|
if value is not None
|
|
199
167
|
},
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/version_1_apis/roborock_client_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/version_1_apis/roborock_mqtt_client_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-2.29.0 → python_roborock-2.29.1}/roborock/version_a01_apis/roborock_client_a01.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|