mirror of
https://github.com/sususweet/midea-meiju-codec.git
synced 2025-12-17 09:55:51 +00:00
feat: add support for T0xC3 heat pump. Fix #46.
This commit is contained in:
@@ -33,6 +33,7 @@ Get devices from MSmartHome/Midea Meiju homes through the network and control th
|
|||||||
- T0xB7 Gas Stove
|
- T0xB7 Gas Stove
|
||||||
- T0xB8 Smart Robot Vacuum
|
- T0xB8 Smart Robot Vacuum
|
||||||
- T0xBF Microwave Steam Oven
|
- T0xBF Microwave Steam Oven
|
||||||
|
- T0xC3 Heat Pump
|
||||||
- T0xCA French Door Refrigerator
|
- T0xCA French Door Refrigerator
|
||||||
- T0xCC Central Air Conditioning (Ducted) Wi-Fi Controller
|
- T0xCC Central Air Conditioning (Ducted) Wi-Fi Controller
|
||||||
- T0xCD Air Energy Water Heater
|
- T0xCD Air Energy Water Heater
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
- T0xB7 燃气灶
|
- T0xB7 燃气灶
|
||||||
- T0xB8 智能扫地机器人
|
- T0xB8 智能扫地机器人
|
||||||
- T0xBF 微波炉
|
- T0xBF 微波炉
|
||||||
|
- T0xC3 热泵
|
||||||
- T0xCA 对开门冰箱
|
- T0xCA 对开门冰箱
|
||||||
- T0xCC 中央空调(风管机)Wi-Fi线控器
|
- T0xCC 中央空调(风管机)Wi-Fi线控器
|
||||||
- T0xCD 空气能热水器
|
- T0xCD 空气能热水器
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ clouds = {
|
|||||||
"app_key": "ac21b9f9cbfe4ca5a88562ef25e2b768",
|
"app_key": "ac21b9f9cbfe4ca5a88562ef25e2b768",
|
||||||
"iot_key": bytes.fromhex(format(7882822598523843940, 'x')).decode(),
|
"iot_key": bytes.fromhex(format(7882822598523843940, 'x')).decode(),
|
||||||
"hmac_key": bytes.fromhex(format(117390035944627627450677220413733956185864939010425, 'x')).decode(),
|
"hmac_key": bytes.fromhex(format(117390035944627627450677220413733956185864939010425, 'x')).decode(),
|
||||||
# "api_url": "https://mp-eu-prod.appsmb.com/mas/v5/app/proxy?alias=",
|
"api_url": "https://mp-eu-prod.appsmb.com/mas/v5/app/proxy?alias=",
|
||||||
"api_url": "https://mp-prod.appsmb.com/mas/v5/app/proxy?alias=",
|
# "api_url": "https://mp-prod.appsmb.com/mas/v5/app/proxy?alias=",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -642,7 +642,7 @@ class MSmartHomeCloud(MideaCloud):
|
|||||||
self._api_url = api_url
|
self._api_url = api_url
|
||||||
|
|
||||||
async def login(self) -> bool:
|
async def login(self) -> bool:
|
||||||
await self._re_route()
|
# await self._re_route()
|
||||||
if login_id := await self._get_login_id():
|
if login_id := await self._get_login_id():
|
||||||
self._login_id = login_id
|
self._login_id = login_id
|
||||||
iot_data = self._make_general_data()
|
iot_data = self._make_general_data()
|
||||||
@@ -734,6 +734,93 @@ class MSmartHomeCloud(MideaCloud):
|
|||||||
await fp.write(stream)
|
await fp.write(stream)
|
||||||
return fnm
|
return fnm
|
||||||
|
|
||||||
|
async def download_plugin(
|
||||||
|
self, path: str,
|
||||||
|
appliance_code: str,
|
||||||
|
smart_product_id: str,
|
||||||
|
device_type: int,
|
||||||
|
sn: str,
|
||||||
|
sn8: str,
|
||||||
|
model_number: str | None,
|
||||||
|
manufacturer_code: str = "0000",
|
||||||
|
):
|
||||||
|
# 构建 applianceList,根据传入的参数动态生成
|
||||||
|
appliance_info = {
|
||||||
|
"appModel": sn8,
|
||||||
|
"appEnterprise": manufacturer_code,
|
||||||
|
"appType": f"0x{device_type:02X}",
|
||||||
|
"applianceCode": str(appliance_code) if isinstance(appliance_code, int) else appliance_code,
|
||||||
|
"smartProductId": str(smart_product_id) if isinstance(smart_product_id, int) else smart_product_id,
|
||||||
|
"modelNumber": model_number or "0",
|
||||||
|
"versionCode": 0
|
||||||
|
}
|
||||||
|
appliance_list = [appliance_info]
|
||||||
|
data = {
|
||||||
|
"applianceList": json.dumps(appliance_list),
|
||||||
|
"iotAppId": self.APP_ID,
|
||||||
|
"match": "1",
|
||||||
|
"clientType": "1",
|
||||||
|
"clientVersion": 201
|
||||||
|
}
|
||||||
|
fnm = None
|
||||||
|
if response := await self._api_request(
|
||||||
|
endpoint="/v1/plugin/update/getPluginV3",
|
||||||
|
data=data
|
||||||
|
):
|
||||||
|
# response 是 {"list": [...]}
|
||||||
|
plugin_list = response.get("list", [])
|
||||||
|
if not plugin_list:
|
||||||
|
MideaLogger.warning(f"No plugin found for device type 0x{device_type:02X}, sn: {sn}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 找到匹配的设备(优先匹配 applianceCode,其次匹配 appType)
|
||||||
|
matched_plugin = None
|
||||||
|
# 首先尝试精确匹配 applianceCode
|
||||||
|
for plugin in plugin_list:
|
||||||
|
if plugin.get("applianceCode") == sn and plugin.get("appType") == f"0x{device_type:02X}":
|
||||||
|
matched_plugin = plugin
|
||||||
|
break
|
||||||
|
|
||||||
|
# 如果没有精确匹配,使用第一个匹配 appType 的
|
||||||
|
if not matched_plugin:
|
||||||
|
for plugin in plugin_list:
|
||||||
|
if plugin.get("appType") == f"0x{device_type:02X}":
|
||||||
|
matched_plugin = plugin
|
||||||
|
break
|
||||||
|
|
||||||
|
if not matched_plugin:
|
||||||
|
MideaLogger.warning(f"No matching plugin found for device type 0x{device_type:02X}, sn: {sn}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 下载 zip 文件
|
||||||
|
zip_url = matched_plugin.get("url")
|
||||||
|
zip_title = matched_plugin.get("title", f"plugin_0x{device_type:02X}.zip")
|
||||||
|
|
||||||
|
if not zip_url:
|
||||||
|
MideaLogger.warning(f"No download URL found for plugin: {zip_title}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 确保目录存在
|
||||||
|
os.makedirs(path, exist_ok=True)
|
||||||
|
|
||||||
|
res = await self._session.get(zip_url)
|
||||||
|
if res.status == 200:
|
||||||
|
zip_data = await res.read()
|
||||||
|
if zip_data:
|
||||||
|
fnm = f"{path}/{zip_title}"
|
||||||
|
async with aiofiles.open(fnm, "wb") as fp:
|
||||||
|
await fp.write(zip_data)
|
||||||
|
MideaLogger.info(f"Downloaded plugin file: {fnm}")
|
||||||
|
else:
|
||||||
|
MideaLogger.warning(f"Downloaded zip file is empty: {zip_url}")
|
||||||
|
else:
|
||||||
|
MideaLogger.warning(f"Failed to download plugin, status: {res.status}, url: {zip_url}")
|
||||||
|
except Exception as e:
|
||||||
|
MideaLogger.error(f"Error downloading plugin: {e}")
|
||||||
|
traceback.print_exc()
|
||||||
|
return fnm
|
||||||
|
|
||||||
async def send_cloud(self, appliance_code: int, data: bytearray):
|
async def send_cloud(self, appliance_code: int, data: bytearray):
|
||||||
appliance_code = str(appliance_code)
|
appliance_code = str(appliance_code)
|
||||||
params = {
|
params = {
|
||||||
|
|||||||
75
custom_components/midea_auto_cloud/device_mapping/T0xC3.py
Normal file
75
custom_components/midea_auto_cloud/device_mapping/T0xC3.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
from homeassistant.const import Platform, UnitOfTemperature, PRECISION_HALVES, CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, \
|
||||||
|
CONCENTRATION_PARTS_PER_MILLION
|
||||||
|
from homeassistant.components.sensor import SensorStateClass, SensorDeviceClass
|
||||||
|
from homeassistant.components.switch import SwitchDeviceClass
|
||||||
|
|
||||||
|
DEVICE_MAPPING = {
|
||||||
|
"default": {
|
||||||
|
"rationale": ["off", "on"],
|
||||||
|
"queries": [{}],
|
||||||
|
"centralized": [],
|
||||||
|
"entities": {
|
||||||
|
Platform.CLIMATE: {
|
||||||
|
"Zone1": {
|
||||||
|
"power": "zone1_power_state",
|
||||||
|
"hvac_modes": {
|
||||||
|
"off": {"zone1_power_state": "off"},
|
||||||
|
"heat": {"zone1_power_state": "on"},
|
||||||
|
},
|
||||||
|
"target_temperature": "room_temp_set",
|
||||||
|
"current_temperature": "T4",
|
||||||
|
"min_temp": "room_min_set_temp",
|
||||||
|
"max_temp": "room_max_set_temp",
|
||||||
|
"temperature_unit": UnitOfTemperature.CELSIUS,
|
||||||
|
"precision": PRECISION_HALVES,
|
||||||
|
},
|
||||||
|
"DHW": {
|
||||||
|
"power": "dhw_power_state",
|
||||||
|
"hvac_modes": {
|
||||||
|
"off": {"dhw_power_state": "off"},
|
||||||
|
"heat": {"dhw_power_state": "on"},
|
||||||
|
},
|
||||||
|
"target_temperature": "dhw_temp_set",
|
||||||
|
"current_temperature": "T4",
|
||||||
|
"min_temp": "dhw_min_set_temp",
|
||||||
|
"max_temp": "dhw_max_set_temp",
|
||||||
|
"temperature_unit": UnitOfTemperature.CELSIUS,
|
||||||
|
"precision": PRECISION_HALVES,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Platform.SWITCH: {
|
||||||
|
"fastdhw_state": {
|
||||||
|
"device_class": SwitchDeviceClass.SWITCH,
|
||||||
|
"translation_key": "fastdhw_state",
|
||||||
|
},
|
||||||
|
"forcetbh_state": {
|
||||||
|
"device_class": SwitchDeviceClass.SWITCH,
|
||||||
|
"translation_key": "forcetbh_state",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Platform.SENSOR: {
|
||||||
|
"run_mode_set": {
|
||||||
|
"device_class": SensorDeviceClass.ENUM,
|
||||||
|
"translation_key": "mode",
|
||||||
|
},
|
||||||
|
"room_temp_set": {
|
||||||
|
"device_class": SensorDeviceClass.TEMPERATURE,
|
||||||
|
"unit_of_measurement": UnitOfTemperature.CELSIUS,
|
||||||
|
"state_class": SensorStateClass.MEASUREMENT,
|
||||||
|
"translation_key": "room_temperature",
|
||||||
|
},
|
||||||
|
"t4": {
|
||||||
|
"device_class": SensorDeviceClass.TEMPERATURE,
|
||||||
|
"unit_of_measurement": UnitOfTemperature.CELSIUS,
|
||||||
|
"state_class": SensorStateClass.MEASUREMENT,
|
||||||
|
"translation_key": "outside_temperature",
|
||||||
|
},
|
||||||
|
"tank_actual_temp":{
|
||||||
|
"device_class": SensorDeviceClass.TEMPERATURE,
|
||||||
|
"unit_of_measurement": UnitOfTemperature.CELSIUS,
|
||||||
|
"state_class": SensorStateClass.MEASUREMENT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -125,7 +125,7 @@ class MideaEntity(CoordinatorEntity[MideaDataUpdateCoordinator], Entity):
|
|||||||
@property
|
@property
|
||||||
def device_attributes(self) -> dict:
|
def device_attributes(self) -> dict:
|
||||||
"""Return device attributes."""
|
"""Return device attributes."""
|
||||||
return self.coordinator.data.attributes
|
return self.coordinator.data.attributes if self.coordinator.data else {}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def available(self) -> bool:
|
def available(self) -> bool:
|
||||||
|
|||||||
@@ -335,6 +335,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Zone1": {
|
||||||
|
"name": "区域1"
|
||||||
|
},
|
||||||
|
"DHW": {
|
||||||
|
"name": "DHW"
|
||||||
|
},
|
||||||
"colmo_turing_central_ac_climate": {
|
"colmo_turing_central_ac_climate": {
|
||||||
"name": "Thermostat",
|
"name": "Thermostat",
|
||||||
"state_attributes": {
|
"state_attributes": {
|
||||||
@@ -2567,6 +2573,12 @@
|
|||||||
},
|
},
|
||||||
"water_model_go_out": {
|
"water_model_go_out": {
|
||||||
"name": "Away Mode"
|
"name": "Away Mode"
|
||||||
|
},
|
||||||
|
"fastdhw_state": {
|
||||||
|
"name": "Fast Hot Water"
|
||||||
|
},
|
||||||
|
"forcetbh_state": {
|
||||||
|
"name": "Force Standby"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -335,6 +335,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Zone1": {
|
||||||
|
"name": "区域1"
|
||||||
|
},
|
||||||
|
"DHW": {
|
||||||
|
"name": "DHW"
|
||||||
|
},
|
||||||
"colmo_turing_central_ac_climate": {
|
"colmo_turing_central_ac_climate": {
|
||||||
"name": "温控器",
|
"name": "温控器",
|
||||||
"state_attributes": {
|
"state_attributes": {
|
||||||
@@ -2571,6 +2577,12 @@
|
|||||||
},
|
},
|
||||||
"water_model_go_out": {
|
"water_model_go_out": {
|
||||||
"name": "外出模式"
|
"name": "外出模式"
|
||||||
|
},
|
||||||
|
"fastdhw_state": {
|
||||||
|
"name": "快速生活热水"
|
||||||
|
},
|
||||||
|
"forcetbh_state": {
|
||||||
|
"name": "强制待机"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user