Obfuscated diagnostics; fixed IP auto-update; cleaned logs
This commit is contained in:
committed by
GitHub Actions
parent
cdfe8e4906
commit
6be13c5ba0
@@ -5,27 +5,26 @@ import time
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.device_registry import DeviceEntry
|
|
||||||
import homeassistant.helpers.entity_registry as er
|
import homeassistant.helpers.entity_registry as er
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_CLIENT_ID,
|
CONF_CLIENT_ID,
|
||||||
CONF_CLIENT_SECRET,
|
CONF_CLIENT_SECRET,
|
||||||
CONF_REGION,
|
|
||||||
CONF_DEVICE_ID,
|
CONF_DEVICE_ID,
|
||||||
CONF_DEVICES,
|
CONF_DEVICES,
|
||||||
CONF_ENTITIES,
|
CONF_ENTITIES,
|
||||||
CONF_HOST,
|
CONF_HOST,
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
CONF_PLATFORM,
|
CONF_PLATFORM,
|
||||||
|
CONF_REGION,
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
EVENT_HOMEASSISTANT_STOP,
|
EVENT_HOMEASSISTANT_STOP,
|
||||||
SERVICE_RELOAD,
|
SERVICE_RELOAD,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
from homeassistant.helpers.device_registry import DeviceEntry
|
||||||
from homeassistant.helpers.event import async_track_time_interval
|
from homeassistant.helpers.event import async_track_time_interval
|
||||||
|
|
||||||
from .cloud_api import TuyaCloudApi
|
from .cloud_api import TuyaCloudApi
|
||||||
@@ -66,7 +65,6 @@ SERVICE_SET_DP_SCHEMA = vol.Schema(
|
|||||||
async def async_setup(hass: HomeAssistant, config: dict):
|
async def async_setup(hass: HomeAssistant, config: dict):
|
||||||
"""Set up the LocalTuya integration component."""
|
"""Set up the LocalTuya integration component."""
|
||||||
hass.data.setdefault(DOMAIN, {})
|
hass.data.setdefault(DOMAIN, {})
|
||||||
print("SETUP")
|
|
||||||
|
|
||||||
device_cache = {}
|
device_cache = {}
|
||||||
|
|
||||||
@@ -134,10 +132,11 @@ async def async_setup(hass: HomeAssistant, config: dict):
|
|||||||
# settings triggers a reload of the config entry, which tears down the device
|
# settings triggers a reload of the config entry, which tears down the device
|
||||||
# so no need to connect in that case.
|
# so no need to connect in that case.
|
||||||
if updated:
|
if updated:
|
||||||
new_data[ATTR_UPDATED_AT] = str(int(time.time() * 1000))
|
_LOGGER.debug(
|
||||||
hass.config_entries.async_update_entry(
|
"Updating keys for device %s: %s %s", device_id, device_ip, product_key
|
||||||
entry, data=new_data
|
|
||||||
)
|
)
|
||||||
|
new_data[ATTR_UPDATED_AT] = str(int(time.time() * 1000))
|
||||||
|
hass.config_entries.async_update_entry(entry, data=new_data)
|
||||||
device = hass.data[DOMAIN][TUYA_DEVICES][device_id]
|
device = hass.data[DOMAIN][TUYA_DEVICES][device_id]
|
||||||
if not device.connected:
|
if not device.connected:
|
||||||
device.async_connect()
|
device.async_connect()
|
||||||
@@ -148,26 +147,17 @@ async def async_setup(hass: HomeAssistant, config: dict):
|
|||||||
if not device.connected:
|
if not device.connected:
|
||||||
device.async_connect()
|
device.async_connect()
|
||||||
|
|
||||||
discovery = TuyaDiscovery(_device_discovered)
|
|
||||||
|
|
||||||
def _shutdown(event):
|
def _shutdown(event):
|
||||||
"""Clean up resources when shutting down."""
|
"""Clean up resources when shutting down."""
|
||||||
discovery.close()
|
discovery.close()
|
||||||
|
|
||||||
try:
|
|
||||||
await discovery.start()
|
|
||||||
hass.data[DOMAIN][DATA_DISCOVERY] = discovery
|
|
||||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _shutdown)
|
|
||||||
except Exception: # pylint: disable=broad-except
|
|
||||||
_LOGGER.exception("failed to set up discovery")
|
|
||||||
|
|
||||||
async def _async_reconnect(now):
|
async def _async_reconnect(now):
|
||||||
"""Try connecting to devices not already connected to."""
|
"""Try connecting to devices not already connected to."""
|
||||||
for device_id, device in hass.data[DOMAIN][TUYA_DEVICES].items():
|
for device_id, device in hass.data[DOMAIN][TUYA_DEVICES].items():
|
||||||
if not device.connected:
|
if not device.connected:
|
||||||
device.async_connect()
|
device.async_connect()
|
||||||
|
|
||||||
# async_track_time_interval(hass, _async_reconnect, RECONNECT_INTERVAL)
|
async_track_time_interval(hass, _async_reconnect, RECONNECT_INTERVAL)
|
||||||
|
|
||||||
hass.helpers.service.async_register_admin_service(
|
hass.helpers.service.async_register_admin_service(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
@@ -179,6 +169,14 @@ async def async_setup(hass: HomeAssistant, config: dict):
|
|||||||
DOMAIN, SERVICE_SET_DP, _handle_set_dp, schema=SERVICE_SET_DP_SCHEMA
|
DOMAIN, SERVICE_SET_DP, _handle_set_dp, schema=SERVICE_SET_DP_SCHEMA
|
||||||
)
|
)
|
||||||
|
|
||||||
|
discovery = TuyaDiscovery(_device_discovered)
|
||||||
|
try:
|
||||||
|
await discovery.start()
|
||||||
|
hass.data[DOMAIN][DATA_DISCOVERY] = discovery
|
||||||
|
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _shutdown)
|
||||||
|
except Exception: # pylint: disable=broad-except
|
||||||
|
_LOGGER.exception("failed to set up discovery")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@@ -228,7 +226,6 @@ async def async_migrate_entry(hass, config_entry: ConfigEntry):
|
|||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
print("SETUP ENTRY STARTED!")
|
|
||||||
"""Set up LocalTuya integration from a config entry."""
|
"""Set up LocalTuya integration from a config entry."""
|
||||||
unsub_listener = entry.add_update_listener(update_listener)
|
unsub_listener = entry.add_update_listener(update_listener)
|
||||||
hass.data[DOMAIN][UNSUB_LISTENER] = unsub_listener
|
hass.data[DOMAIN][UNSUB_LISTENER] = unsub_listener
|
||||||
@@ -244,19 +241,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
_LOGGER.error("Cloud API connection failed: %s", res)
|
_LOGGER.error("Cloud API connection failed: %s", res)
|
||||||
_LOGGER.info("Cloud API connection succeeded.")
|
_LOGGER.info("Cloud API connection succeeded.")
|
||||||
res = await tuya_api.async_get_devices_list()
|
res = await tuya_api.async_get_devices_list()
|
||||||
for dev_id, dev in tuya_api._device_list.items():
|
|
||||||
_LOGGER.debug(
|
|
||||||
"Cloud device: %s \t dev_id %s \t key %s", dev["name"], dev["id"], dev["local_key"]
|
|
||||||
)
|
|
||||||
hass.data[DOMAIN][DATA_CLOUD] = tuya_api
|
hass.data[DOMAIN][DATA_CLOUD] = tuya_api
|
||||||
|
|
||||||
# device = TuyaDevice(hass, entry.data)
|
|
||||||
#
|
|
||||||
# hass.data[DOMAIN][entry.entry_id] = {
|
|
||||||
# UNSUB_LISTENER: unsub_listener,
|
|
||||||
# TUYA_DEVICE: device,
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
async def setup_entities(dev_id):
|
async def setup_entities(dev_id):
|
||||||
dev_entry = entry.data[CONF_DEVICES][dev_id]
|
dev_entry = entry.data[CONF_DEVICES][dev_id]
|
||||||
device = TuyaDevice(hass, entry, dev_id)
|
device = TuyaDevice(hass, entry, dev_id)
|
||||||
@@ -272,19 +258,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
device.async_connect()
|
device.async_connect()
|
||||||
|
|
||||||
await async_remove_orphan_entities(hass, entry)
|
await async_remove_orphan_entities(hass, entry)
|
||||||
print("SETUP_ENTITIES for {} ENDED".format(dev_id))
|
|
||||||
|
|
||||||
for dev_id in entry.data[CONF_DEVICES]:
|
for dev_id in entry.data[CONF_DEVICES]:
|
||||||
hass.async_create_task(setup_entities(dev_id))
|
hass.async_create_task(setup_entities(dev_id))
|
||||||
|
|
||||||
print("SETUP ENTRY ENDED!")
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
"""Unload a config entry."""
|
"""Unload a config entry."""
|
||||||
# print("ASYNC_UNLOAD_ENTRY INVOKED...")
|
|
||||||
platforms = {}
|
platforms = {}
|
||||||
for dev_id, dev_entry in entry.data[CONF_DEVICES].items():
|
for dev_id, dev_entry in entry.data[CONF_DEVICES].items():
|
||||||
for entity in dev_entry[CONF_ENTITIES]:
|
for entity in dev_entry[CONF_ENTITIES]:
|
||||||
@@ -301,20 +283,18 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
|
|
||||||
hass.data[DOMAIN][UNSUB_LISTENER]()
|
hass.data[DOMAIN][UNSUB_LISTENER]()
|
||||||
for dev_id, device in hass.data[DOMAIN][TUYA_DEVICES].items():
|
for dev_id, device in hass.data[DOMAIN][TUYA_DEVICES].items():
|
||||||
|
if device.connected:
|
||||||
await device.close()
|
await device.close()
|
||||||
|
|
||||||
if unload_ok:
|
if unload_ok:
|
||||||
hass.data[DOMAIN][TUYA_DEVICES] = {}
|
hass.data[DOMAIN][TUYA_DEVICES] = {}
|
||||||
|
|
||||||
# print("ASYNC_UNLOAD_ENTRY ENDED")
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def update_listener(hass, config_entry):
|
async def update_listener(hass, config_entry):
|
||||||
"""Update listener."""
|
"""Update listener."""
|
||||||
print("UPDATE_LISTENER INVOKED")
|
|
||||||
await hass.config_entries.async_reload(config_entry.entry_id)
|
await hass.config_entries.async_reload(config_entry.entry_id)
|
||||||
print("UPDATE_LISTENER RELOADED {}".format(config_entry.entry_id))
|
|
||||||
|
|
||||||
|
|
||||||
async def async_remove_config_entry_device(
|
async def async_remove_config_entry_device(
|
||||||
@@ -323,9 +303,18 @@ async def async_remove_config_entry_device(
|
|||||||
"""Remove a config entry from a device."""
|
"""Remove a config entry from a device."""
|
||||||
dev_id = list(device_entry.identifiers)[0][1].split("_")[-1]
|
dev_id = list(device_entry.identifiers)[0][1].split("_")[-1]
|
||||||
|
|
||||||
|
ent_reg = await er.async_get_registry(hass)
|
||||||
|
entities = {
|
||||||
|
ent.unique_id: ent.entity_id
|
||||||
|
for ent in er.async_entries_for_config_entry(ent_reg, config_entry.entry_id)
|
||||||
|
if dev_id in ent.unique_id
|
||||||
|
}
|
||||||
|
for entity_id in entities.values():
|
||||||
|
ent_reg.async_remove(entity_id)
|
||||||
|
|
||||||
if dev_id not in config_entry.data[CONF_DEVICES]:
|
if dev_id not in config_entry.data[CONF_DEVICES]:
|
||||||
_LOGGER.debug(
|
_LOGGER.info(
|
||||||
"Device ID %s not found in config entry: finalizing device removal", dev_id
|
"Device %s not found in config entry: finalizing device removal", dev_id
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -340,15 +329,7 @@ async def async_remove_config_entry_device(
|
|||||||
data=new_data,
|
data=new_data,
|
||||||
)
|
)
|
||||||
|
|
||||||
ent_reg = await er.async_get_registry(hass)
|
_LOGGER.info("Device %s removed.", dev_id)
|
||||||
entities = {
|
|
||||||
ent.unique_id: ent.entity_id
|
|
||||||
for ent in er.async_entries_for_config_entry(ent_reg, config_entry.entry_id)
|
|
||||||
if dev_id in ent.unique_id
|
|
||||||
}
|
|
||||||
for entity_id in entities.values():
|
|
||||||
ent_reg.async_remove(entity_id)
|
|
||||||
print("REMOVED {}".format(entity_id))
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -361,11 +342,8 @@ async def async_remove_orphan_entities(hass, entry):
|
|||||||
ent.unique_id: ent.entity_id
|
ent.unique_id: ent.entity_id
|
||||||
for ent in er.async_entries_for_config_entry(ent_reg, entry.entry_id)
|
for ent in er.async_entries_for_config_entry(ent_reg, entry.entry_id)
|
||||||
}
|
}
|
||||||
print("ENTITIES ORPHAN {}".format(entities))
|
_LOGGER.info("ENTITIES ORPHAN %s", entities)
|
||||||
return
|
return
|
||||||
res = ent_reg.async_remove("switch.aa")
|
|
||||||
print("RESULT ORPHAN {}".format(res))
|
|
||||||
# del entities[101]
|
|
||||||
|
|
||||||
for entity in entry.data[CONF_ENTITIES]:
|
for entity in entry.data[CONF_ENTITIES]:
|
||||||
if entity[CONF_ID] in entities:
|
if entity[CONF_ID] in entities:
|
||||||
|
@@ -11,18 +11,18 @@ from homeassistant.components.climate import (
|
|||||||
ClimateEntity,
|
ClimateEntity,
|
||||||
)
|
)
|
||||||
from homeassistant.components.climate.const import (
|
from homeassistant.components.climate.const import (
|
||||||
|
CURRENT_HVAC_HEAT,
|
||||||
|
CURRENT_HVAC_IDLE,
|
||||||
HVAC_MODE_AUTO,
|
HVAC_MODE_AUTO,
|
||||||
HVAC_MODE_HEAT,
|
HVAC_MODE_HEAT,
|
||||||
HVAC_MODE_OFF,
|
HVAC_MODE_OFF,
|
||||||
|
PRESET_AWAY,
|
||||||
|
PRESET_ECO,
|
||||||
|
PRESET_HOME,
|
||||||
|
PRESET_NONE,
|
||||||
SUPPORT_PRESET_MODE,
|
SUPPORT_PRESET_MODE,
|
||||||
SUPPORT_TARGET_TEMPERATURE,
|
SUPPORT_TARGET_TEMPERATURE,
|
||||||
SUPPORT_TARGET_TEMPERATURE_RANGE,
|
SUPPORT_TARGET_TEMPERATURE_RANGE,
|
||||||
CURRENT_HVAC_IDLE,
|
|
||||||
CURRENT_HVAC_HEAT,
|
|
||||||
PRESET_NONE,
|
|
||||||
PRESET_ECO,
|
|
||||||
PRESET_AWAY,
|
|
||||||
PRESET_HOME,
|
|
||||||
)
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_TEMPERATURE,
|
ATTR_TEMPERATURE,
|
||||||
@@ -37,21 +37,21 @@ from homeassistant.const import (
|
|||||||
from .common import LocalTuyaEntity, async_setup_entry
|
from .common import LocalTuyaEntity, async_setup_entry
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_CURRENT_TEMPERATURE_DP,
|
CONF_CURRENT_TEMPERATURE_DP,
|
||||||
CONF_MAX_TEMP_DP,
|
CONF_ECO_DP,
|
||||||
CONF_MIN_TEMP_DP,
|
CONF_ECO_VALUE,
|
||||||
CONF_PRECISION,
|
|
||||||
CONF_TARGET_PRECISION,
|
|
||||||
CONF_TARGET_TEMPERATURE_DP,
|
|
||||||
CONF_TEMPERATURE_STEP,
|
|
||||||
CONF_HVAC_MODE_DP,
|
|
||||||
CONF_HVAC_MODE_SET,
|
|
||||||
CONF_HEURISTIC_ACTION,
|
CONF_HEURISTIC_ACTION,
|
||||||
CONF_HVAC_ACTION_DP,
|
CONF_HVAC_ACTION_DP,
|
||||||
CONF_HVAC_ACTION_SET,
|
CONF_HVAC_ACTION_SET,
|
||||||
CONF_ECO_DP,
|
CONF_HVAC_MODE_DP,
|
||||||
CONF_ECO_VALUE,
|
CONF_HVAC_MODE_SET,
|
||||||
|
CONF_MAX_TEMP_DP,
|
||||||
|
CONF_MIN_TEMP_DP,
|
||||||
|
CONF_PRECISION,
|
||||||
CONF_PRESET_DP,
|
CONF_PRESET_DP,
|
||||||
CONF_PRESET_SET,
|
CONF_PRESET_SET,
|
||||||
|
CONF_TARGET_PRECISION,
|
||||||
|
CONF_TARGET_TEMPERATURE_DP,
|
||||||
|
CONF_TEMPERATURE_STEP,
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@@ -3,9 +3,10 @@ import functools
|
|||||||
import hashlib
|
import hashlib
|
||||||
import hmac
|
import hmac
|
||||||
import json
|
import json
|
||||||
import requests
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
# Signature algorithm.
|
# Signature algorithm.
|
||||||
def calc_sign(msg, key):
|
def calc_sign(msg, key):
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
"""Code shared between all platforms."""
|
"""Code shared between all platforms."""
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from datetime import timedelta
|
|
||||||
import time
|
import time
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_DEVICE_ID,
|
CONF_DEVICE_ID,
|
||||||
@@ -16,11 +16,11 @@ from homeassistant.const import (
|
|||||||
CONF_SCAN_INTERVAL,
|
CONF_SCAN_INTERVAL,
|
||||||
)
|
)
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers.event import async_track_time_interval
|
|
||||||
from homeassistant.helpers.dispatcher import (
|
from homeassistant.helpers.dispatcher import (
|
||||||
async_dispatcher_connect,
|
async_dispatcher_connect,
|
||||||
async_dispatcher_send,
|
async_dispatcher_send,
|
||||||
)
|
)
|
||||||
|
from homeassistant.helpers.event import async_track_time_interval
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
|
|
||||||
from . import pytuya
|
from . import pytuya
|
||||||
@@ -28,8 +28,8 @@ from .const import (
|
|||||||
ATTR_UPDATED_AT,
|
ATTR_UPDATED_AT,
|
||||||
CONF_LOCAL_KEY,
|
CONF_LOCAL_KEY,
|
||||||
CONF_PROTOCOL_VERSION,
|
CONF_PROTOCOL_VERSION,
|
||||||
DOMAIN,
|
|
||||||
DATA_CLOUD,
|
DATA_CLOUD,
|
||||||
|
DOMAIN,
|
||||||
TUYA_DEVICES,
|
TUYA_DEVICES,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -74,6 +74,10 @@ async def async_setup_entry(
|
|||||||
|
|
||||||
if len(entities_to_setup) > 0:
|
if len(entities_to_setup) > 0:
|
||||||
|
|
||||||
|
if dev_id not in hass.data[DOMAIN][TUYA_DEVICES]:
|
||||||
|
print("STRANO: {}".format(hass.data[DOMAIN][TUYA_DEVICES]))
|
||||||
|
return
|
||||||
|
|
||||||
tuyainterface = hass.data[DOMAIN][TUYA_DEVICES][dev_id]
|
tuyainterface = hass.data[DOMAIN][TUYA_DEVICES][dev_id]
|
||||||
|
|
||||||
dps_config_fields = list(get_dps_for_platform(flow_schema))
|
dps_config_fields = list(get_dps_for_platform(flow_schema))
|
||||||
@@ -127,7 +131,7 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
self._config_entry = config_entry
|
self._config_entry = config_entry
|
||||||
self._dev_config_entry = config_entry.data[CONF_DEVICES][dev_id]
|
self._dev_config_entry = config_entry.data[CONF_DEVICES][dev_id].copy()
|
||||||
self._interface = None
|
self._interface = None
|
||||||
self._status = {}
|
self._status = {}
|
||||||
self.dps_to_request = {}
|
self.dps_to_request = {}
|
||||||
@@ -205,9 +209,7 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger):
|
|||||||
|
|
||||||
except Exception as e: # pylint: disable=broad-except
|
except Exception as e: # pylint: disable=broad-except
|
||||||
self.exception(f"Connect to {self._dev_config_entry[CONF_HOST]} failed")
|
self.exception(f"Connect to {self._dev_config_entry[CONF_HOST]} failed")
|
||||||
self.error("BBBB: %s", type(type(e)))
|
if "json.decode" in str(type(e)):
|
||||||
if 'json.decode' in str(type(e)):
|
|
||||||
self.error("BBBB2")
|
|
||||||
await self.update_local_key()
|
await self.update_local_key()
|
||||||
|
|
||||||
if self._interface is not None:
|
if self._interface is not None:
|
||||||
@@ -220,7 +222,6 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger):
|
|||||||
await self._hass.data[DOMAIN][DATA_CLOUD].async_get_devices_list()
|
await self._hass.data[DOMAIN][DATA_CLOUD].async_get_devices_list()
|
||||||
cloud_devs = self._hass.data[DOMAIN][DATA_CLOUD]._device_list
|
cloud_devs = self._hass.data[DOMAIN][DATA_CLOUD]._device_list
|
||||||
if dev_id in cloud_devs:
|
if dev_id in cloud_devs:
|
||||||
old_key = self._local_key
|
|
||||||
self._local_key = cloud_devs[dev_id].get(CONF_LOCAL_KEY)
|
self._local_key = cloud_devs[dev_id].get(CONF_LOCAL_KEY)
|
||||||
new_data = self._config_entry.data.copy()
|
new_data = self._config_entry.data.copy()
|
||||||
new_data[CONF_DEVICES][dev_id][CONF_LOCAL_KEY] = self._local_key
|
new_data[CONF_DEVICES][dev_id][CONF_LOCAL_KEY] = self._local_key
|
||||||
@@ -229,10 +230,7 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger):
|
|||||||
self._config_entry,
|
self._config_entry,
|
||||||
data=new_data,
|
data=new_data,
|
||||||
)
|
)
|
||||||
self.debug(
|
self.info("local_key updated for device %s.", dev_id)
|
||||||
"New local key for %s: from %s to %s",
|
|
||||||
dev_id, old_key, self._local_key
|
|
||||||
)
|
|
||||||
|
|
||||||
async def _async_refresh(self, _now):
|
async def _async_refresh(self, _now):
|
||||||
if self._interface is not None:
|
if self._interface is not None:
|
||||||
@@ -250,7 +248,7 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger):
|
|||||||
self._disconnect_task()
|
self._disconnect_task()
|
||||||
self.debug(
|
self.debug(
|
||||||
"Closed connection with device %s.",
|
"Closed connection with device %s.",
|
||||||
self._dev_config_entry[CONF_FRIENDLY_NAME]
|
self._dev_config_entry[CONF_FRIENDLY_NAME],
|
||||||
)
|
)
|
||||||
|
|
||||||
async def set_dp(self, state, dp_index):
|
async def set_dp(self, state, dp_index):
|
||||||
|
@@ -9,6 +9,8 @@ import homeassistant.helpers.entity_registry as er
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from homeassistant import config_entries, core, exceptions
|
from homeassistant import config_entries, core, exceptions
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
|
CONF_CLIENT_ID,
|
||||||
|
CONF_CLIENT_SECRET,
|
||||||
CONF_DEVICE_ID,
|
CONF_DEVICE_ID,
|
||||||
CONF_DEVICES,
|
CONF_DEVICES,
|
||||||
CONF_ENTITIES,
|
CONF_ENTITIES,
|
||||||
@@ -18,29 +20,27 @@ from homeassistant.const import (
|
|||||||
CONF_MODEL,
|
CONF_MODEL,
|
||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
CONF_PLATFORM,
|
CONF_PLATFORM,
|
||||||
CONF_SCAN_INTERVAL,
|
|
||||||
CONF_CLIENT_ID,
|
|
||||||
CONF_CLIENT_SECRET,
|
|
||||||
CONF_REGION,
|
CONF_REGION,
|
||||||
|
CONF_SCAN_INTERVAL,
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
)
|
)
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
|
|
||||||
from .cloud_api import TuyaCloudApi
|
from .cloud_api import TuyaCloudApi
|
||||||
from .common import async_config_entry_by_device_id, pytuya
|
from .common import pytuya
|
||||||
from .const import (
|
from .const import (
|
||||||
|
ATTR_UPDATED_AT,
|
||||||
CONF_ACTION,
|
CONF_ACTION,
|
||||||
CONF_ADD_DEVICE,
|
CONF_ADD_DEVICE,
|
||||||
|
CONF_DPS_STRINGS,
|
||||||
CONF_EDIT_DEVICE,
|
CONF_EDIT_DEVICE,
|
||||||
CONF_SETUP_CLOUD,
|
|
||||||
CONF_LOCAL_KEY,
|
CONF_LOCAL_KEY,
|
||||||
CONF_PRODUCT_NAME,
|
CONF_PRODUCT_NAME,
|
||||||
CONF_PROTOCOL_VERSION,
|
CONF_PROTOCOL_VERSION,
|
||||||
|
CONF_SETUP_CLOUD,
|
||||||
CONF_USER_ID,
|
CONF_USER_ID,
|
||||||
CONF_DPS_STRINGS,
|
|
||||||
ATTR_UPDATED_AT,
|
|
||||||
DATA_DISCOVERY,
|
|
||||||
DATA_CLOUD,
|
DATA_CLOUD,
|
||||||
|
DATA_DISCOVERY,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
PLATFORMS,
|
PLATFORMS,
|
||||||
)
|
)
|
||||||
@@ -304,11 +304,6 @@ class LocaltuyaConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
placeholders = {"msg": res["msg"]}
|
placeholders = {"msg": res["msg"]}
|
||||||
|
|
||||||
defaults = {}
|
defaults = {}
|
||||||
defaults[CONF_REGION] = "eu"
|
|
||||||
defaults[CONF_CLIENT_ID] = "xxx"
|
|
||||||
defaults[CONF_CLIENT_SECRET] = "xxx"
|
|
||||||
defaults[CONF_USER_ID] = "xxx"
|
|
||||||
defaults[CONF_USERNAME] = "xxx"
|
|
||||||
defaults.update(user_input or {})
|
defaults.update(user_input or {})
|
||||||
|
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
@@ -383,16 +378,17 @@ class LocalTuyaOptionsFlowHandler(config_entries.OptionsFlow):
|
|||||||
cloud_devs = cloud_api._device_list
|
cloud_devs = cloud_api._device_list
|
||||||
for dev_id, dev in new_data[CONF_DEVICES].items():
|
for dev_id, dev in new_data[CONF_DEVICES].items():
|
||||||
if CONF_MODEL not in dev and dev_id in cloud_devs:
|
if CONF_MODEL not in dev and dev_id in cloud_devs:
|
||||||
new_data[CONF_DEVICES][dev_id][CONF_MODEL] = cloud_devs[dev_id].get(
|
model = cloud_devs[dev_id].get(CONF_PRODUCT_NAME)
|
||||||
CONF_PRODUCT_NAME
|
new_data[CONF_DEVICES][dev_id][CONF_MODEL] = model
|
||||||
)
|
|
||||||
new_data[ATTR_UPDATED_AT] = str(int(time.time() * 1000))
|
new_data[ATTR_UPDATED_AT] = str(int(time.time() * 1000))
|
||||||
|
|
||||||
self.hass.config_entries.async_update_entry(
|
self.hass.config_entries.async_update_entry(
|
||||||
self.config_entry,
|
self.config_entry,
|
||||||
data=new_data,
|
data=new_data,
|
||||||
)
|
)
|
||||||
return self.async_create_entry(title=new_data.get(CONF_USERNAME), data={})
|
return self.async_create_entry(
|
||||||
|
title=new_data.get(CONF_USERNAME), data={}
|
||||||
|
)
|
||||||
errors["base"] = res["reason"]
|
errors["base"] = res["reason"]
|
||||||
placeholders = {"msg": res["msg"]}
|
placeholders = {"msg": res["msg"]}
|
||||||
|
|
||||||
@@ -559,7 +555,6 @@ class LocalTuyaOptionsFlowHandler(config_entries.OptionsFlow):
|
|||||||
CONF_ENTITIES: self.entities,
|
CONF_ENTITIES: self.entities,
|
||||||
}
|
}
|
||||||
|
|
||||||
# entry = async_config_entry_by_device_id(self.hass, self.unique_id)
|
|
||||||
dev_id = self.device_data.get(CONF_DEVICE_ID)
|
dev_id = self.device_data.get(CONF_DEVICE_ID)
|
||||||
if dev_id in self.config_entry.data[CONF_DEVICES]:
|
if dev_id in self.config_entry.data[CONF_DEVICES]:
|
||||||
self.hass.config_entries.async_update_entry(
|
self.hass.config_entries.async_update_entry(
|
||||||
|
@@ -1,13 +1,18 @@
|
|||||||
"""Diagnostics support for LocalTuya."""
|
"""Diagnostics support for LocalTuya."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_DEVICES
|
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, CONF_DEVICES
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.device_registry import DeviceEntry
|
from homeassistant.helpers.device_registry import DeviceEntry
|
||||||
|
|
||||||
from .const import DOMAIN, DATA_CLOUD
|
from .const import CONF_LOCAL_KEY, CONF_USER_ID, DATA_CLOUD, DOMAIN
|
||||||
|
|
||||||
|
CLOUD_DEVICES = "cloud_devices"
|
||||||
|
DEVICE_CONFIG = "device_config"
|
||||||
|
DEVICE_CLOUD_INFO = "device_cloud_info"
|
||||||
|
|
||||||
|
|
||||||
async def async_get_config_entry_diagnostics(
|
async def async_get_config_entry_diagnostics(
|
||||||
@@ -15,14 +20,20 @@ async def async_get_config_entry_diagnostics(
|
|||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Return diagnostics for a config entry."""
|
"""Return diagnostics for a config entry."""
|
||||||
data = {}
|
data = {}
|
||||||
data = {**entry.data}
|
data = entry.data.copy()
|
||||||
# print("DATA is {}".format(data))
|
|
||||||
tuya_api = hass.data[DOMAIN][DATA_CLOUD]
|
tuya_api = hass.data[DOMAIN][DATA_CLOUD]
|
||||||
data["cloud_devices"] = tuya_api._device_list
|
|
||||||
|
|
||||||
# censoring private information
|
# censoring private information
|
||||||
# data["token"] = re.sub(r"[^\-]", "*", data["token"])
|
for field in [CONF_CLIENT_ID, CONF_CLIENT_SECRET, CONF_USER_ID]:
|
||||||
# data["userId"] = re.sub(r"[^\-]", "*", data["userId"])
|
data[field] = f"{data[field][0:3]}...{data[field][-3:]}"
|
||||||
|
for dev_id, dev in data[CONF_DEVICES].items():
|
||||||
|
local_key = data[CONF_DEVICES][dev_id][CONF_LOCAL_KEY]
|
||||||
|
local_key_obfuscated = f"{local_key[0:3]}...{local_key[-3:]}"
|
||||||
|
data[CONF_DEVICES][dev_id][CONF_LOCAL_KEY] = local_key_obfuscated
|
||||||
|
data[CLOUD_DEVICES] = tuya_api._device_list
|
||||||
|
for dev_id, dev in data[CLOUD_DEVICES].items():
|
||||||
|
local_key = data[CLOUD_DEVICES][dev_id][CONF_LOCAL_KEY]
|
||||||
|
local_key_obfuscated = f"{local_key[0:3]}...{local_key[-3:]}"
|
||||||
|
data[CLOUD_DEVICES][dev_id][CONF_LOCAL_KEY] = local_key_obfuscated
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
@@ -32,9 +43,14 @@ async def async_get_device_diagnostics(
|
|||||||
"""Return diagnostics for a device entry."""
|
"""Return diagnostics for a device entry."""
|
||||||
data = {}
|
data = {}
|
||||||
dev_id = list(device.identifiers)[0][1].split("_")[-1]
|
dev_id = list(device.identifiers)[0][1].split("_")[-1]
|
||||||
data["device_config"] = entry.data[CONF_DEVICES][dev_id]
|
data[DEVICE_CONFIG] = entry.data[CONF_DEVICES][dev_id]
|
||||||
|
local_key = data[DEVICE_CONFIG][CONF_LOCAL_KEY]
|
||||||
|
data[DEVICE_CONFIG][CONF_LOCAL_KEY] = f"{local_key[0:3]}...{local_key[-3:]}"
|
||||||
|
|
||||||
tuya_api = hass.data[DOMAIN][DATA_CLOUD]
|
tuya_api = hass.data[DOMAIN][DATA_CLOUD]
|
||||||
if dev_id in tuya_api._device_list:
|
if dev_id in tuya_api._device_list:
|
||||||
data["device_cloud_info"] = tuya_api._device_list[dev_id]
|
data[DEVICE_CLOUD_INFO] = tuya_api._device_list[dev_id]
|
||||||
|
local_key = data[DEVICE_CLOUD_INFO][CONF_LOCAL_KEY]
|
||||||
|
data[DEVICE_CLOUD_INFO][CONF_LOCAL_KEY] = f"{local_key[0:3]}...{local_key[-3:]}"
|
||||||
# data["log"] = hass.data[DOMAIN][CONF_DEVICES][dev_id].logger.retrieve_log()
|
# data["log"] = hass.data[DOMAIN][CONF_DEVICES][dev_id].logger.retrieve_log()
|
||||||
return data
|
return data
|
||||||
|
@@ -7,41 +7,40 @@ from homeassistant.components.vacuum import (
|
|||||||
DOMAIN,
|
DOMAIN,
|
||||||
STATE_CLEANING,
|
STATE_CLEANING,
|
||||||
STATE_DOCKED,
|
STATE_DOCKED,
|
||||||
STATE_IDLE,
|
|
||||||
STATE_RETURNING,
|
|
||||||
STATE_PAUSED,
|
|
||||||
STATE_ERROR,
|
STATE_ERROR,
|
||||||
|
STATE_IDLE,
|
||||||
|
STATE_PAUSED,
|
||||||
|
STATE_RETURNING,
|
||||||
SUPPORT_BATTERY,
|
SUPPORT_BATTERY,
|
||||||
SUPPORT_FAN_SPEED,
|
SUPPORT_FAN_SPEED,
|
||||||
|
SUPPORT_LOCATE,
|
||||||
SUPPORT_PAUSE,
|
SUPPORT_PAUSE,
|
||||||
SUPPORT_RETURN_HOME,
|
SUPPORT_RETURN_HOME,
|
||||||
SUPPORT_START,
|
SUPPORT_START,
|
||||||
SUPPORT_STATE,
|
SUPPORT_STATE,
|
||||||
SUPPORT_STATUS,
|
SUPPORT_STATUS,
|
||||||
SUPPORT_STOP,
|
SUPPORT_STOP,
|
||||||
SUPPORT_LOCATE,
|
|
||||||
StateVacuumEntity,
|
StateVacuumEntity,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .common import LocalTuyaEntity, async_setup_entry
|
from .common import LocalTuyaEntity, async_setup_entry
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_POWERGO_DP,
|
|
||||||
CONF_IDLE_STATUS_VALUE,
|
|
||||||
CONF_RETURNING_STATUS_VALUE,
|
|
||||||
CONF_DOCKED_STATUS_VALUE,
|
|
||||||
CONF_BATTERY_DP,
|
CONF_BATTERY_DP,
|
||||||
CONF_MODE_DP,
|
|
||||||
CONF_MODES,
|
|
||||||
CONF_FAN_SPEED_DP,
|
|
||||||
CONF_FAN_SPEEDS,
|
|
||||||
CONF_CLEAN_TIME_DP,
|
|
||||||
CONF_CLEAN_AREA_DP,
|
CONF_CLEAN_AREA_DP,
|
||||||
CONF_CLEAN_RECORD_DP,
|
CONF_CLEAN_RECORD_DP,
|
||||||
CONF_LOCATE_DP,
|
CONF_CLEAN_TIME_DP,
|
||||||
|
CONF_DOCKED_STATUS_VALUE,
|
||||||
|
CONF_FAN_SPEED_DP,
|
||||||
|
CONF_FAN_SPEEDS,
|
||||||
CONF_FAULT_DP,
|
CONF_FAULT_DP,
|
||||||
|
CONF_IDLE_STATUS_VALUE,
|
||||||
|
CONF_LOCATE_DP,
|
||||||
|
CONF_MODE_DP,
|
||||||
|
CONF_MODES,
|
||||||
CONF_PAUSED_STATE,
|
CONF_PAUSED_STATE,
|
||||||
|
CONF_POWERGO_DP,
|
||||||
CONF_RETURN_MODE,
|
CONF_RETURN_MODE,
|
||||||
|
CONF_RETURNING_STATUS_VALUE,
|
||||||
CONF_STOP_STATUS,
|
CONF_STOP_STATUS,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user