forked from HomeAssistant/midea-meiju-codec
Remove file sync read warning
This commit is contained in:
@@ -4,6 +4,7 @@ import voluptuous as vol
|
|||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.util.json import load_json
|
from homeassistant.util.json import load_json
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from homeassistant.helpers.json import save_json
|
from homeassistant.helpers.json import save_json
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -11,7 +12,7 @@ except ImportError:
|
|||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.core import (
|
from homeassistant.core import (
|
||||||
HomeAssistant,
|
HomeAssistant,
|
||||||
ServiceCall
|
ServiceCall
|
||||||
)
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
@@ -42,7 +43,7 @@ from .const import (
|
|||||||
CONF_SN8,
|
CONF_SN8,
|
||||||
CONF_SN,
|
CONF_SN,
|
||||||
CONF_MODEL_NUMBER,
|
CONF_MODEL_NUMBER,
|
||||||
CONF_LUA_FILE, CONF_SERVERS
|
CONF_SERVERS
|
||||||
)
|
)
|
||||||
# 账号型:登录云端、获取设备列表,并为每台设备建立协调器(无本地控制)
|
# 账号型:登录云端、获取设备列表,并为每台设备建立协调器(无本地控制)
|
||||||
from .const import CONF_PASSWORD as CONF_PASSWORD_KEY, CONF_SERVER as CONF_SERVER_KEY
|
from .const import CONF_PASSWORD as CONF_PASSWORD_KEY, CONF_SERVER as CONF_SERVER_KEY
|
||||||
@@ -57,6 +58,7 @@ PLATFORMS: list[Platform] = [
|
|||||||
Platform.FAN
|
Platform.FAN
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def get_sn8_used(hass: HomeAssistant, sn8):
|
def get_sn8_used(hass: HomeAssistant, sn8):
|
||||||
entries = hass.config_entries.async_entries(DOMAIN)
|
entries = hass.config_entries.async_entries(DOMAIN)
|
||||||
count = 0
|
count = 0
|
||||||
@@ -74,13 +76,26 @@ def remove_device_config(hass: HomeAssistant, sn8):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def load_device_config(hass: HomeAssistant, device_type, sn8):
|
async def load_device_config(hass: HomeAssistant, device_type, sn8):
|
||||||
os.makedirs(hass.config.path(CONFIG_PATH), exist_ok=True)
|
def _ensure_dir_and_load(path_dir: str, path_file: str):
|
||||||
|
os.makedirs(path_dir, exist_ok=True)
|
||||||
|
return load_json(path_file, default={})
|
||||||
|
|
||||||
|
config_dir = hass.config.path(CONFIG_PATH)
|
||||||
config_file = hass.config.path(f"{CONFIG_PATH}/{sn8}.json")
|
config_file = hass.config.path(f"{CONFIG_PATH}/{sn8}.json")
|
||||||
json_data = load_json(config_file, default={})
|
raw = await hass.async_add_executor_job(_ensure_dir_and_load, config_dir, config_file)
|
||||||
if len(json_data) > 0:
|
json_data = {}
|
||||||
json_data = json_data.get(sn8)
|
if isinstance(raw, dict) and len(raw) > 0:
|
||||||
else:
|
# 兼容两种文件结构:
|
||||||
|
# 1) { "<sn8>": { ...mapping... } }
|
||||||
|
# 2) { ...mapping... }(直接就是映射体)
|
||||||
|
if sn8 in raw:
|
||||||
|
json_data = raw.get(sn8) or {}
|
||||||
|
else:
|
||||||
|
# 如果像映射体(包含 entities/centralized 等关键字段),直接使用
|
||||||
|
if any(k in raw for k in ["entities", "centralized", "queries", "manufacturer"]):
|
||||||
|
json_data = raw
|
||||||
|
if not json_data:
|
||||||
device_path = f".device_mapping.{'T0x%02X' % device_type}"
|
device_path = f".device_mapping.{'T0x%02X' % device_type}"
|
||||||
try:
|
try:
|
||||||
mapping_module = import_module(device_path, __package__)
|
mapping_module = import_module(device_path, __package__)
|
||||||
@@ -90,57 +105,12 @@ def load_device_config(hass: HomeAssistant, device_type, sn8):
|
|||||||
json_data = mapping_module.DEVICE_MAPPING["default"]
|
json_data = mapping_module.DEVICE_MAPPING["default"]
|
||||||
if len(json_data) > 0:
|
if len(json_data) > 0:
|
||||||
save_data = {sn8: json_data}
|
save_data = {sn8: json_data}
|
||||||
save_json(config_file, save_data)
|
# offload save_json as well
|
||||||
|
await hass.async_add_executor_job(save_json, config_file, save_data)
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
MideaLogger.warning(f"Can't load mapping file for type {'T0x%02X' % device_type}")
|
MideaLogger.warning(f"Can't load mapping file for type {'T0x%02X' % device_type}")
|
||||||
return json_data
|
return json_data
|
||||||
|
|
||||||
|
|
||||||
def register_services(hass: HomeAssistant):
|
|
||||||
|
|
||||||
async def async_set_attributes(service: ServiceCall):
|
|
||||||
device_id = service.data.get("device_id")
|
|
||||||
attributes = service.data.get("attributes")
|
|
||||||
MideaLogger.debug(f"Service called: set_attributes, device_id: {device_id}, attributes: {attributes}")
|
|
||||||
try:
|
|
||||||
coordinator: MideaDataUpdateCoordinator = hass.data[DOMAIN][DEVICES][device_id].get("coordinator")
|
|
||||||
except KeyError:
|
|
||||||
MideaLogger.error(f"Failed to call service set_attributes: the device {device_id} isn't exist.")
|
|
||||||
return
|
|
||||||
if coordinator:
|
|
||||||
await coordinator.async_set_attributes(attributes)
|
|
||||||
|
|
||||||
async def async_send_command(service: ServiceCall):
|
|
||||||
device_id = service.data.get("device_id")
|
|
||||||
cmd_type = service.data.get("cmd_type")
|
|
||||||
cmd_body = service.data.get("cmd_body")
|
|
||||||
try:
|
|
||||||
coordinator: MideaDataUpdateCoordinator = hass.data[DOMAIN][DEVICES][device_id].get("coordinator")
|
|
||||||
except KeyError:
|
|
||||||
MideaLogger.error(f"Failed to call service send_command: the device {device_id} isn't exist.")
|
|
||||||
return
|
|
||||||
if coordinator:
|
|
||||||
await coordinator.async_send_command(cmd_type, cmd_body)
|
|
||||||
|
|
||||||
hass.services.async_register(
|
|
||||||
DOMAIN,
|
|
||||||
"set_attributes",
|
|
||||||
async_set_attributes,
|
|
||||||
schema=vol.Schema({
|
|
||||||
vol.Required("device_id"): vol.Coerce(int),
|
|
||||||
vol.Required("attributes"): vol.Any(dict)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
hass.services.async_register(
|
|
||||||
DOMAIN, "send_command", async_send_command,
|
|
||||||
schema=vol.Schema({
|
|
||||||
vol.Required("device_id"): vol.Coerce(int),
|
|
||||||
vol.Required("cmd_type"): vol.In([2, 3]),
|
|
||||||
vol.Required("cmd_body"): str
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def update_listener(hass: HomeAssistant, config_entry: ConfigEntry):
|
async def update_listener(hass: HomeAssistant, config_entry: ConfigEntry):
|
||||||
device_id = config_entry.data.get(CONF_DEVICE_ID)
|
device_id = config_entry.data.get(CONF_DEVICE_ID)
|
||||||
if device_id is not None:
|
if device_id is not None:
|
||||||
@@ -172,8 +142,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType):
|
|||||||
bit_lua = base64.b64decode(BIT_LUA.encode("utf-8")).decode("utf-8")
|
bit_lua = base64.b64decode(BIT_LUA.encode("utf-8")).decode("utf-8")
|
||||||
with open(bit, "wt") as fp:
|
with open(bit, "wt") as fp:
|
||||||
fp.write(bit_lua)
|
fp.write(bit_lua)
|
||||||
|
|
||||||
register_services(hass)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@@ -234,11 +202,10 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry):
|
|||||||
subtype=info.get(CONF_MODEL_NUMBER),
|
subtype=info.get(CONF_MODEL_NUMBER),
|
||||||
sn=info.get(CONF_SN) or info.get("sn"),
|
sn=info.get(CONF_SN) or info.get("sn"),
|
||||||
sn8=info.get(CONF_SN8) or info.get("sn8"),
|
sn8=info.get(CONF_SN8) or info.get("sn8"),
|
||||||
lua_file=None,
|
|
||||||
)
|
)
|
||||||
# 加载并应用设备映射(queries/centralized/calculate),并预置 attributes 键
|
# 加载并应用设备映射(queries/centralized/calculate),并预置 attributes 键
|
||||||
try:
|
try:
|
||||||
mapping = load_device_config(
|
mapping = await load_device_config(
|
||||||
hass,
|
hass,
|
||||||
info.get(CONF_TYPE) or info.get("type"),
|
info.get(CONF_TYPE) or info.get("type"),
|
||||||
info.get(CONF_SN8) or info.get("sn8"),
|
info.get(CONF_SN8) or info.get("sn8"),
|
||||||
@@ -352,11 +319,9 @@ async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry):
|
|||||||
device: MiedaDevice = hass.data[DOMAIN][DEVICES][device_id][CONF_DEVICE]
|
device: MiedaDevice = hass.data[DOMAIN][DEVICES][device_id][CONF_DEVICE]
|
||||||
if device is not None:
|
if device is not None:
|
||||||
if get_sn8_used(hass, device.sn8) == 1:
|
if get_sn8_used(hass, device.sn8) == 1:
|
||||||
lua_file = config_entry.data.get("lua_file")
|
|
||||||
os.remove(lua_file)
|
|
||||||
remove_device_config(hass, device.sn8)
|
remove_device_config(hass, device.sn8)
|
||||||
# device.close()
|
# device.close()
|
||||||
hass.data[DOMAIN][DEVICES].pop(device_id)
|
hass.data[DOMAIN][DEVICES].pop(device_id)
|
||||||
for platform in ALL_PLATFORM:
|
for platform in PLATFORMS:
|
||||||
await hass.config_entries.async_forward_entry_unload(config_entry, platform)
|
await hass.config_entries.async_forward_entry_unload(config_entry, platform)
|
||||||
return True
|
return True
|
||||||
|
@@ -29,7 +29,7 @@ async def async_setup_entry(
|
|||||||
for device_id, info in device_list.items():
|
for device_id, info in device_list.items():
|
||||||
device_type = info.get("type")
|
device_type = info.get("type")
|
||||||
sn8 = info.get("sn8")
|
sn8 = info.get("sn8")
|
||||||
config = load_device_config(hass, device_type, sn8) or {}
|
config = await load_device_config(hass, device_type, sn8) or {}
|
||||||
entities_cfg = (config.get("entities") or {}).get(Platform.BINARY_SENSOR, {})
|
entities_cfg = (config.get("entities") or {}).get(Platform.BINARY_SENSOR, {})
|
||||||
manufacturer = config.get("manufacturer")
|
manufacturer = config.get("manufacturer")
|
||||||
rationale = config.get("rationale")
|
rationale = config.get("rationale")
|
||||||
|
@@ -37,7 +37,7 @@ async def async_setup_entry(
|
|||||||
for device_id, info in device_list.items():
|
for device_id, info in device_list.items():
|
||||||
device_type = info.get("type")
|
device_type = info.get("type")
|
||||||
sn8 = info.get("sn8")
|
sn8 = info.get("sn8")
|
||||||
config = load_device_config(hass, device_type, sn8) or {}
|
config = await load_device_config(hass, device_type, sn8) or {}
|
||||||
entities_cfg = (config.get("entities") or {}).get(Platform.CLIMATE, {})
|
entities_cfg = (config.get("entities") or {}).get(Platform.CLIMATE, {})
|
||||||
manufacturer = config.get("manufacturer")
|
manufacturer = config.get("manufacturer")
|
||||||
rationale = config.get("rationale")
|
rationale = config.get("rationale")
|
||||||
|
@@ -96,7 +96,7 @@ class MideaCloud:
|
|||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
print(response)
|
|
||||||
if int(response["code"]) == 0 and "data" in response:
|
if int(response["code"]) == 0 and "data" in response:
|
||||||
return response["data"]
|
return response["data"]
|
||||||
|
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
import threading
|
import threading
|
||||||
import socket
|
import socket
|
||||||
import time
|
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
from .security import LocalSecurity, MSGTYPE_HANDSHAKE_REQUEST, MSGTYPE_ENCRYPTED_REQUEST
|
from .security import LocalSecurity, MSGTYPE_HANDSHAKE_REQUEST, MSGTYPE_ENCRYPTED_REQUEST
|
||||||
from .packet_builder import PacketBuilder
|
from .packet_builder import PacketBuilder
|
||||||
from .lua_runtime import MideaCodec
|
|
||||||
from .message import MessageQuestCustom
|
from .message import MessageQuestCustom
|
||||||
from .logger import MideaLogger
|
from .logger import MideaLogger
|
||||||
|
|
||||||
@@ -41,8 +39,7 @@ class MiedaDevice(threading.Thread):
|
|||||||
subtype: int | None,
|
subtype: int | None,
|
||||||
connected: bool,
|
connected: bool,
|
||||||
sn: str | None,
|
sn: str | None,
|
||||||
sn8: str | None,
|
sn8: str | None):
|
||||||
lua_file: str | None):
|
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
self._socket = None
|
self._socket = None
|
||||||
self._ip_address = ip_address
|
self._ip_address = ip_address
|
||||||
@@ -74,7 +71,6 @@ class MiedaDevice(threading.Thread):
|
|||||||
self._centralized = []
|
self._centralized = []
|
||||||
self._calculate_get = []
|
self._calculate_get = []
|
||||||
self._calculate_set = []
|
self._calculate_set = []
|
||||||
self._lua_runtime = MideaCodec(lua_file, sn=sn, subtype=subtype) if lua_file is not None else None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_name(self):
|
def device_name(self):
|
||||||
@@ -136,8 +132,6 @@ class MiedaDevice(threading.Thread):
|
|||||||
for attr in self._centralized:
|
for attr in self._centralized:
|
||||||
new_status[attr] = self._attributes.get(attr)
|
new_status[attr] = self._attributes.get(attr)
|
||||||
new_status[attribute] = value
|
new_status[attribute] = value
|
||||||
if set_cmd := self._lua_runtime.build_control(new_status):
|
|
||||||
self._build_send(set_cmd)
|
|
||||||
|
|
||||||
def set_attributes(self, attributes):
|
def set_attributes(self, attributes):
|
||||||
new_status = {}
|
new_status = {}
|
||||||
@@ -148,9 +142,6 @@ class MiedaDevice(threading.Thread):
|
|||||||
if attribute in self._attributes.keys():
|
if attribute in self._attributes.keys():
|
||||||
has_new = True
|
has_new = True
|
||||||
new_status[attribute] = value
|
new_status[attribute] = value
|
||||||
if has_new:
|
|
||||||
if set_cmd := self._lua_runtime.build_control(new_status):
|
|
||||||
self._build_send(set_cmd)
|
|
||||||
|
|
||||||
def set_ip_address(self, ip_address):
|
def set_ip_address(self, ip_address):
|
||||||
MideaLogger.debug(f"Update IP address to {ip_address}")
|
MideaLogger.debug(f"Update IP address to {ip_address}")
|
||||||
@@ -219,72 +210,6 @@ class MiedaDevice(threading.Thread):
|
|||||||
msg = PacketBuilder(self._device_id, bytes_cmd).finalize()
|
msg = PacketBuilder(self._device_id, bytes_cmd).finalize()
|
||||||
self._send_message(msg)
|
self._send_message(msg)
|
||||||
|
|
||||||
def _refresh_status(self):
|
|
||||||
for query in self._queries:
|
|
||||||
if query_cmd := self._lua_runtime.build_query(query):
|
|
||||||
self._build_send(query_cmd)
|
|
||||||
|
|
||||||
def _parse_message(self, msg):
|
|
||||||
if self._protocol == 3:
|
|
||||||
messages, self._buffer = self._security.decode_8370(self._buffer + msg)
|
|
||||||
else:
|
|
||||||
messages, self._buffer = self.fetch_v2_message(self._buffer + msg)
|
|
||||||
if len(messages) == 0:
|
|
||||||
return ParseMessageResult.PADDING
|
|
||||||
for message in messages:
|
|
||||||
if message == b"ERROR":
|
|
||||||
return ParseMessageResult.ERROR
|
|
||||||
payload_len = message[4] + (message[5] << 8) - 56
|
|
||||||
payload_type = message[2] + (message[3] << 8)
|
|
||||||
if payload_type in [0x1001, 0x0001]:
|
|
||||||
# Heartbeat detected
|
|
||||||
pass
|
|
||||||
elif len(message) > 56:
|
|
||||||
cryptographic = message[40:-16]
|
|
||||||
if payload_len % 16 == 0:
|
|
||||||
decrypted = self._security.aes_decrypt(cryptographic)
|
|
||||||
MideaLogger.debug(f"Received: {decrypted.hex().lower()}")
|
|
||||||
if status := self._lua_runtime.decode_status(decrypted.hex()):
|
|
||||||
MideaLogger.debug(f"Decoded: {status}")
|
|
||||||
new_status = {}
|
|
||||||
for single in status.keys():
|
|
||||||
value = status.get(single)
|
|
||||||
if single not in self._attributes or self._attributes[single] != value:
|
|
||||||
self._attributes[single] = value
|
|
||||||
new_status[single] = value
|
|
||||||
if len(new_status) > 0:
|
|
||||||
for c in self._calculate_get:
|
|
||||||
lvalue = c.get("lvalue")
|
|
||||||
rvalue = c.get("rvalue")
|
|
||||||
if lvalue and rvalue:
|
|
||||||
calculate = False
|
|
||||||
for s, v in new_status.items():
|
|
||||||
if rvalue.find(f"[{s}]") >= 0:
|
|
||||||
calculate = True
|
|
||||||
break
|
|
||||||
if calculate:
|
|
||||||
calculate_str1 = \
|
|
||||||
(f"{lvalue.replace('[', 'self._attributes[')} = "
|
|
||||||
f"{rvalue.replace('[', 'self._attributes[')}") \
|
|
||||||
.replace("[","[\"").replace("]","\"]")
|
|
||||||
calculate_str2 = \
|
|
||||||
(f"{lvalue.replace('[', 'new_status[')} = "
|
|
||||||
f"{rvalue.replace('[', 'self._attributes[')}") \
|
|
||||||
.replace("[","[\"").replace("]","\"]")
|
|
||||||
try:
|
|
||||||
exec(calculate_str1)
|
|
||||||
exec(calculate_str2)
|
|
||||||
except Exception:
|
|
||||||
MideaLogger.warning(
|
|
||||||
f"Calculation Error: {lvalue} = {rvalue}", self._device_id
|
|
||||||
)
|
|
||||||
self._update_all(new_status)
|
|
||||||
return ParseMessageResult.SUCCESS
|
|
||||||
|
|
||||||
def _send_heartbeat(self):
|
|
||||||
msg = PacketBuilder(self._device_id, bytearray([0x00])).finalize(msg_type=0)
|
|
||||||
self._send_message(msg)
|
|
||||||
|
|
||||||
def _device_connected(self, connected=True):
|
def _device_connected(self, connected=True):
|
||||||
self._connected = connected
|
self._connected = connected
|
||||||
status = {"connected": connected}
|
status = {"connected": connected}
|
||||||
|
@@ -1,91 +0,0 @@
|
|||||||
import lupa
|
|
||||||
import threading
|
|
||||||
import json
|
|
||||||
from .logger import MideaLogger
|
|
||||||
|
|
||||||
|
|
||||||
class LuaRuntime:
|
|
||||||
def __init__(self, file):
|
|
||||||
self._runtimes = lupa.LuaRuntime()
|
|
||||||
string = f'dofile("{file}")'
|
|
||||||
self._runtimes.execute(string)
|
|
||||||
self._lock = threading.Lock()
|
|
||||||
self._json_to_data = self._runtimes.eval("function(param) return jsonToData(param) end")
|
|
||||||
self._data_to_json = self._runtimes.eval("function(param) return dataToJson(param) end")
|
|
||||||
|
|
||||||
def json_to_data(self, json_value):
|
|
||||||
with self._lock:
|
|
||||||
result = self._json_to_data(json_value)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def data_to_json(self, data_value):
|
|
||||||
with self._lock:
|
|
||||||
result = self._data_to_json(data_value)
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
class MideaCodec(LuaRuntime):
|
|
||||||
def __init__(self, file, sn=None, subtype=None):
|
|
||||||
super().__init__(file)
|
|
||||||
self._sn = sn
|
|
||||||
self._subtype = subtype
|
|
||||||
|
|
||||||
def _build_base_dict(self):
|
|
||||||
device_info ={}
|
|
||||||
if self._sn is not None:
|
|
||||||
device_info["deviceSN"] = self._sn
|
|
||||||
if self._subtype is not None:
|
|
||||||
device_info["deviceSubType"] = self._subtype
|
|
||||||
base_dict = {
|
|
||||||
"deviceinfo": device_info
|
|
||||||
}
|
|
||||||
return base_dict
|
|
||||||
|
|
||||||
def build_query(self, append=None):
|
|
||||||
query_dict = self._build_base_dict()
|
|
||||||
query_dict["query"] = {} if append is None else append
|
|
||||||
json_str = json.dumps(query_dict)
|
|
||||||
try:
|
|
||||||
result = self.json_to_data(json_str)
|
|
||||||
return result
|
|
||||||
except lupa.LuaError as e:
|
|
||||||
MideaLogger.error(f"LuaRuntimeError in build_query {json_str}: {repr(e)}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def build_control(self, append=None):
|
|
||||||
query_dict = self._build_base_dict()
|
|
||||||
query_dict["control"] = {} if append is None else append
|
|
||||||
json_str = json.dumps(query_dict)
|
|
||||||
try:
|
|
||||||
result = self.json_to_data(json_str)
|
|
||||||
return result
|
|
||||||
except lupa.LuaError as e:
|
|
||||||
MideaLogger.error(f"LuaRuntimeError in build_control {json_str}: {repr(e)}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def build_status(self, append=None):
|
|
||||||
query_dict = self._build_base_dict()
|
|
||||||
query_dict["status"] = {} if append is None else append
|
|
||||||
json_str = json.dumps(query_dict)
|
|
||||||
try:
|
|
||||||
result = self.json_to_data(json_str)
|
|
||||||
return result
|
|
||||||
except lupa.LuaError as e:
|
|
||||||
MideaLogger.error(f"LuaRuntimeError in build_status {json_str}: {repr(e)}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def decode_status(self, data: str):
|
|
||||||
data_dict = self._build_base_dict()
|
|
||||||
data_dict["msg"] = {
|
|
||||||
"data": data
|
|
||||||
}
|
|
||||||
json_str = json.dumps(data_dict)
|
|
||||||
try:
|
|
||||||
result = self.data_to_json(json_str)
|
|
||||||
status = json.loads(result)
|
|
||||||
return status.get("status")
|
|
||||||
except lupa.LuaError as e:
|
|
||||||
MideaLogger.error(f"LuaRuntimeError in decode_status {data}: {repr(e)}")
|
|
||||||
return None
|
|
||||||
|
|
@@ -17,7 +17,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
for device_id, info in device_list.items():
|
for device_id, info in device_list.items():
|
||||||
device_type = info.get("type")
|
device_type = info.get("type")
|
||||||
sn8 = info.get("sn8")
|
sn8 = info.get("sn8")
|
||||||
config = load_device_config(hass, device_type, sn8) or {}
|
config = await load_device_config(hass, device_type, sn8) or {}
|
||||||
entities_cfg = (config.get("entities") or {}).get(Platform.FAN, {})
|
entities_cfg = (config.get("entities") or {}).get(Platform.FAN, {})
|
||||||
manufacturer = config.get("manufacturer")
|
manufacturer = config.get("manufacturer")
|
||||||
rationale = config.get("rationale")
|
rationale = config.get("rationale")
|
||||||
|
@@ -6,6 +6,6 @@
|
|||||||
"documentation": "https://github.com/sususweet/midea-auto-codec#readme",
|
"documentation": "https://github.com/sususweet/midea-auto-codec#readme",
|
||||||
"iot_class": "cloud_push",
|
"iot_class": "cloud_push",
|
||||||
"issue_tracker": "https://github.com/sususweet/midea-auto-codec/issues",
|
"issue_tracker": "https://github.com/sususweet/midea-auto-codec/issues",
|
||||||
"requirements": ["lupa>=2.0"],
|
"requirements": [],
|
||||||
"version": "v0.0.3"
|
"version": "v0.0.5"
|
||||||
}
|
}
|
@@ -17,7 +17,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
for device_id, info in device_list.items():
|
for device_id, info in device_list.items():
|
||||||
device_type = info.get("type")
|
device_type = info.get("type")
|
||||||
sn8 = info.get("sn8")
|
sn8 = info.get("sn8")
|
||||||
config = load_device_config(hass, device_type, sn8) or {}
|
config = await load_device_config(hass, device_type, sn8) or {}
|
||||||
entities_cfg = (config.get("entities") or {}).get(Platform.SELECT, {})
|
entities_cfg = (config.get("entities") or {}).get(Platform.SELECT, {})
|
||||||
manufacturer = config.get("manufacturer")
|
manufacturer = config.get("manufacturer")
|
||||||
rationale = config.get("rationale")
|
rationale = config.get("rationale")
|
||||||
|
@@ -26,7 +26,7 @@ async def async_setup_entry(
|
|||||||
for device_id, info in device_list.items():
|
for device_id, info in device_list.items():
|
||||||
device_type = info.get("type")
|
device_type = info.get("type")
|
||||||
sn8 = info.get("sn8")
|
sn8 = info.get("sn8")
|
||||||
config = load_device_config(hass, device_type, sn8) or {}
|
config = await load_device_config(hass, device_type, sn8) or {}
|
||||||
entities_cfg = (config.get("entities") or {}).get(Platform.SENSOR, {})
|
entities_cfg = (config.get("entities") or {}).get(Platform.SENSOR, {})
|
||||||
manufacturer = config.get("manufacturer")
|
manufacturer = config.get("manufacturer")
|
||||||
rationale = config.get("rationale")
|
rationale = config.get("rationale")
|
||||||
|
@@ -20,7 +20,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
for device_id, info in device_list.items():
|
for device_id, info in device_list.items():
|
||||||
device_type = info.get("type")
|
device_type = info.get("type")
|
||||||
sn8 = info.get("sn8")
|
sn8 = info.get("sn8")
|
||||||
config = load_device_config(hass, device_type, sn8) or {}
|
config = await load_device_config(hass, device_type, sn8) or {}
|
||||||
entities_cfg = (config.get("entities") or {}).get(Platform.WATER_HEATER, {})
|
entities_cfg = (config.get("entities") or {}).get(Platform.WATER_HEATER, {})
|
||||||
manufacturer = config.get("manufacturer")
|
manufacturer = config.get("manufacturer")
|
||||||
rationale = config.get("rationale")
|
rationale = config.get("rationale")
|
||||||
|
Reference in New Issue
Block a user