|
72 | 72 | "api_url": "https://mapp.appsmb.com", # codespell:ignore
|
73 | 73 | },
|
74 | 74 | "Toshiba Iolife": {
|
75 |
| - "class_name": "MideaAirCloud", |
| 75 | + "class_name": "ToshibaIOLife", |
76 | 76 | "app_id": "1203",
|
77 | 77 | "app_key": "09c4d09f0da1513bb62dc7b6b0af9c11",
|
78 | 78 | "api_url": "https://toshiba-app.smartmidea.net", # codespell:ignore
|
@@ -989,6 +989,107 @@ async def list_appliances(
|
989 | 989 | return None
|
990 | 990 |
|
991 | 991 |
|
| 992 | +class ToshibaIOLife(MideaAirCloud): |
| 993 | + """ Toshiba IOLife """ |
| 994 | + async def list_appliance_types( |
| 995 | + self, |
| 996 | + ) -> dict[int, dict[str, Any]] | None: |
| 997 | + """ List Toshiba IOLife device types """ |
| 998 | + data = self._make_general_data() |
| 999 | + data.update({"applianceType": "0xFF"}) |
| 1000 | + if response := await self._api_request( |
| 1001 | + endpoint="/v1/appliance/type/list/get", |
| 1002 | + data=data, |
| 1003 | + ): |
| 1004 | + return(data) |
| 1005 | + return None |
| 1006 | + |
| 1007 | + async def list_appliances( |
| 1008 | + self, |
| 1009 | + ) -> dict[int, dict[str, Any]] | None: |
| 1010 | + """ Get Toshiba IOLife devices.""" |
| 1011 | + data = self._make_general_data() |
| 1012 | + if response := await self._api_request( |
| 1013 | + endpoint="/v2/appliance/user/list/get", |
| 1014 | + data=data, |
| 1015 | + ): |
| 1016 | + appliances = {} |
| 1017 | + for appliance in response["list"]: |
| 1018 | + try: |
| 1019 | + model_number = int(appliance.get("modelNumber", 0)) |
| 1020 | + except ValueError: |
| 1021 | + model_number = 0 |
| 1022 | + |
| 1023 | + # Skip virtual batch devices: |
| 1024 | + if appliance.get("type") == "0x_BATCH_AC": |
| 1025 | + continue |
| 1026 | + if appliance.get("id") == "virtual_ag_0xAC": |
| 1027 | + continue |
| 1028 | + device_info = { |
| 1029 | + "name": appliance.get("name"), |
| 1030 | + "type": int(appliance.get("type"), 16), |
| 1031 | + "sn": appliance.get("sn"), |
| 1032 | + "sn8": "", |
| 1033 | + "model_number": model_number, |
| 1034 | + "manufacturer_code": appliance.get("enterpriseCode", "0000"), |
| 1035 | + "model": "", |
| 1036 | + "online": appliance.get("onlineStatus") == "1", |
| 1037 | + } |
| 1038 | + serial_num = device_info.get("sn") |
| 1039 | + device_info["sn8"] = ( |
| 1040 | + serial_num[9:17] |
| 1041 | + if (serial_num and len(serial_num) > SN8_MIN_SERIAL_LENGTH) |
| 1042 | + else "" |
| 1043 | + ) |
| 1044 | + device_info["model"] = device_info.get("sn8") |
| 1045 | + appliances[int(appliance["id"])] = device_info |
| 1046 | + return appliances |
| 1047 | + return None |
| 1048 | + |
| 1049 | + |
| 1050 | + # FIXME: this isn't working: |
| 1051 | + async def download_lua( |
| 1052 | + self, |
| 1053 | + path: str, |
| 1054 | + device_type: int, |
| 1055 | + sn: str, |
| 1056 | + model_number: str | None = None, |
| 1057 | + manufacturer_code: str = "0000", |
| 1058 | + ) -> str | None: |
| 1059 | + """Download lua integration.""" |
| 1060 | + data = self._make_general_data() |
| 1061 | + data.update( |
| 1062 | + { |
| 1063 | + "appId": self._app_id, |
| 1064 | + "appKey": self._app_key, |
| 1065 | + "applianceMFCode": manufacturer_code, |
| 1066 | + "applianceType": hex(device_type), |
| 1067 | + "modelNumber": "", |
| 1068 | + "applianceSn": sn, |
| 1069 | + "version": "0", |
| 1070 | + }) |
| 1071 | + if model_number is not None: |
| 1072 | + data["modelNumber"] = model_number |
| 1073 | + fnm = None |
| 1074 | + if response := await self._api_request( |
| 1075 | + endpoint="/v1/appliance/protocol/lua/luaGet", # FIXME: Wrong URL? |
| 1076 | + data=data, |
| 1077 | + ): |
| 1078 | + res = await self._session.get(response["url"]) |
| 1079 | + if res.status == HTTPStatus.OK: |
| 1080 | + lua = await res.text() |
| 1081 | + if lua: |
| 1082 | + stream = ( |
| 1083 | + 'local bit = require "bit"\n' |
| 1084 | + + self._security.aes_decrypt_with_fixed_key(lua) |
| 1085 | + ) |
| 1086 | + stream = stream.replace("\r\n", "\n") |
| 1087 | + fnm = f"{path}/{response['fileName']}" |
| 1088 | + async with aiofiles.open(fnm, "w") as fp: |
| 1089 | + await fp.write(stream) |
| 1090 | + return str(fnm) if fnm else None |
| 1091 | + |
| 1092 | + |
992 | 1093 | def get_midea_cloud(
|
993 | 1094 | cloud_name: str,
|
994 | 1095 | session: ClientSession,
|
|
0 commit comments