Skip to content

Commit

Permalink
feat: add product v4 and downloading code (#267)
Browse files Browse the repository at this point in the history
* feat: add product v4 and downloading code

* fix: remove got message
  • Loading branch information
Lash-L authored Jan 9, 2025
1 parent e42729a commit b669117
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 30 deletions.
42 changes: 22 additions & 20 deletions roborock/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -893,26 +893,28 @@ class RoborockProductSpec(RoborockBase):

@dataclass
class RoborockProduct(RoborockBase):
id: int
name: str
model: str
packagename: str
ssid: str
picurl: str
cardpicurl: str
medium_cardpicurl: str
resetwifipicurl: str
resetwifitext: dict
tuyaid: str
status: int
rriotid: str
cardspec: str
pictures: list
nc_mode: str
scope: None
product_tags: list
agreements: list
plugin_pic_url: None
id: int | None = None
name: str | None = None
model: str | None = None
packagename: str | None = None
ssid: str | None = None
picurl: str | None = None
cardpicurl: str | None = None
mediumCardpicurl: str | None = None
resetwifipicurl: str | None = None
configPicUrl: str | None = None
pluginPicUrl: str | None = None
resetwifitext: dict | None = None
tuyaid: str | None = None
status: int | None = None
rriotid: str | None = None
pictures: list | None = None
ncMode: str | None = None
scope: str | None = None
product_tags: list | None = None
agreements: list | None = None
cardspec: str | None = None
plugin_pic_url: str | None = None
products_specification: RoborockProductSpec | None = None

def __post_init__(self):
Expand Down
6 changes: 6 additions & 0 deletions roborock/version_1_apis/roborock_client_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,12 @@ def on_message_received(self, messages: list[RoborockMessage]) -> None:
consumable = Consumable.from_dict(value)
for listener in self.listener_model.protocol_handlers.get(data_protocol, []):
listener(consumable)
else:
self._logger.warning(
f"Unknown data protocol {data_point_number}, please create an "
f"issue on the python-roborock repository"
)
self._logger.info(data)
return
except ValueError:
self._logger.warning(
Expand Down
40 changes: 30 additions & 10 deletions roborock/web_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ async def _get_base_url(self) -> str:
raise RoborockMissingParameters(
"You are missing parameters for this request, are you sure you " "entered your username?"
)
raise RoborockUrlException(response.get("error"))
raise RoborockUrlException(f"error code: {response_code} msg: {response.get('error')}")
response_data = response.get("data")
if response_data is None:
raise RoborockUrlException("response does not have 'data'")
Expand Down Expand Up @@ -276,7 +276,7 @@ async def get_products(self, user_data: UserData) -> ProductResponse:
product_request = PreparedRequest(base_url, {"header_clientid": header_clientid})
product_response = await product_request.request(
"get",
"/api/v3/product",
"/api/v4/product",
headers={"Authorization": user_data.token},
)
if product_response is None:
Expand All @@ -288,24 +288,44 @@ async def get_products(self, user_data: UserData) -> ProductResponse:
return ProductResponse.from_dict(result)
raise RoborockException("product result was an unexpected type")

async def download_code(self, user_data: UserData, product_id: int):
base_url = await self._get_base_url()
header_clientid = self._get_header_client_id()
product_request = PreparedRequest(base_url, {"header_clientid": header_clientid})
request = {"apilevel": 99999, "productids": [product_id], "type": 2}
response = await product_request.request(
"post",
"/api/v1/appplugin",
json=request,
headers={"Authorization": user_data.token, "Content-Type": "application/json"},
)
return response["data"][0]["url"]

async def download_category_code(self, user_data: UserData):
base_url = await self._get_base_url()
header_clientid = self._get_header_client_id()
product_request = PreparedRequest(base_url, {"header_clientid": header_clientid})
response = await product_request.request(
"get",
"api/v1/plugins?apiLevel=99999&type=2",
headers={
"Authorization": user_data.token,
},
)
return {r["category"]: r["url"] for r in response["data"]["categoryPluginList"]}


class PreparedRequest:
def __init__(self, base_url: str, base_headers: dict | None = None) -> None:
self.base_url = base_url
self.base_headers = base_headers or {}

async def request(self, method: str, url: str, params=None, data=None, headers=None) -> dict:
async def request(self, method: str, url: str, params=None, data=None, headers=None, json=None) -> dict:
_url = "/".join(s.strip("/") for s in [self.base_url, url])
_headers = {**self.base_headers, **(headers or {})}
async with aiohttp.ClientSession() as session:
try:
async with session.request(
method,
_url,
params=params,
data=data,
headers=_headers,
) as resp:
async with session.request(method, _url, params=params, data=data, headers=_headers, json=json) as resp:
return await resp.json()
except ContentTypeError as err:
"""If we get an error, lets log everything for debugging."""
Expand Down

0 comments on commit b669117

Please sign in to comment.