Example #1
0
async def _init_tuya_sdk(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    entry_data = entry_decrypt(hass, entry, entry.data)
    project_type = ProjectType(entry_data[CONF_PROJECT_TYPE])

    api = TuyaOpenAPI(
        entry_data[CONF_ENDPOINT],
        entry_data[CONF_ACCESS_ID],
        entry_data[CONF_ACCESS_SECRET],
        project_type,
    )

    api.set_dev_channel("hass")

    if project_type == ProjectType.INDUSTY_SOLUTIONS:
        response = await hass.async_add_executor_job(api.login,
                                                     entry_data[CONF_USERNAME],
                                                     entry_data[CONF_PASSWORD])
    else:
        response = await hass.async_add_executor_job(
            api.login,
            entry_data[CONF_USERNAME],
            entry_data[CONF_PASSWORD],
            entry_data[CONF_COUNTRY_CODE],
            entry_data[CONF_APP_TYPE],
        )

    if response.get("success", False) is False:
        _LOGGER.error("Tuya login error response: %s", response)
        return False

    tuya_mq = TuyaOpenMQ(api)
    tuya_mq.start()

    device_manager = TuyaDeviceManager(api, tuya_mq)

    # Get device list
    home_manager = TuyaHomeManager(api, tuya_mq, device_manager)
    await hass.async_add_executor_job(home_manager.update_device_cache)
    hass.data[DOMAIN][entry.entry_id][TUYA_HOME_MANAGER] = home_manager

    listener = DeviceListener(hass, entry)
    hass.data[DOMAIN][entry.entry_id][TUYA_MQTT_LISTENER] = listener
    device_manager.add_device_listener(listener)
    hass.data[DOMAIN][entry.entry_id][TUYA_DEVICE_MANAGER] = device_manager

    # Clean up device entities
    await cleanup_device_registry(hass, entry)

    _LOGGER.debug("init support type->%s", PLATFORMS)

    hass.config_entries.async_setup_platforms(entry, PLATFORMS)

    return True
def _init_tuya_sdk(hass: HomeAssistant, entry_data: dict) -> TuyaDeviceManager:
    api = TuyaOpenAPI(entry_data[CONF_ENDPOINT], entry_data[CONF_ACCESS_ID],
                      entry_data[CONF_ACCESS_SECRET])
    api.set_dev_channel('hass')

    response = api.login(entry_data[CONF_USERNAME], entry_data[CONF_PASSWORD])
    if response.get('success', False) == False:
        _LOGGER.error(
            "Tuya login error response: %s",
            response,
        )
        return False

    mq = TuyaOpenMQ(api)
    mq.start()

    # Get device list
    devIds = []
    assetManager = TuyaAssetManager(api)
    response = assetManager.getAssetList()
    assets = response.get('result', {}).get('assets', [])
    for asset in assets:
        asset_id = asset['asset_id']
        devIds += assetManager.getDeviceList(asset_id)

    # Update device status
    deviceManager = TuyaDeviceManager(api, mq)
    deviceManager.updateDeviceCaches(devIds)

    # Create ha devices
    haDevices = []
    for (devId, device) in deviceManager.deviceMap.items():
        haDevice = crete_tuya_ha_device(device, deviceManager)
        if haDevice:
            haDevices.append(haDevice)

    hass.data[DOMAIN] = {
        'haDevices': haDevices,
    }

    # Set mqtt listener
    def _onMessage(msg):
        devId = msg.get('data', {}).get('devId', '')
        haDevices = hass.data[DOMAIN]['haDevices']
        for haDevice in haDevices:
            if haDevice.tuyaDevice.id == devId:
                haDevice.schedule_update_ha_state()

    mq.add_message_listener(_onMessage)

    return True
Example #3
0
async def _init_tuya_sdk(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    auth_type = AuthType(entry.data[CONF_AUTH_TYPE])
    api = TuyaOpenAPI(
        endpoint=entry.data[CONF_ENDPOINT],
        access_id=entry.data[CONF_ACCESS_ID],
        access_secret=entry.data[CONF_ACCESS_SECRET],
        auth_type=auth_type,
    )

    api.set_dev_channel("hass")

    if auth_type == AuthType.CUSTOM:
        response = await hass.async_add_executor_job(
            api.connect, entry.data[CONF_USERNAME], entry.data[CONF_PASSWORD]
        )
    else:
        response = await hass.async_add_executor_job(
            api.connect,
            entry.data[CONF_USERNAME],
            entry.data[CONF_PASSWORD],
            entry.data[CONF_COUNTRY_CODE],
            entry.data[CONF_APP_TYPE],
        )

    if response.get("success", False) is False:
        _LOGGER.error("Tuya login error response: %s", response)
        return False

    tuya_mq = TuyaOpenMQ(api)
    tuya_mq.start()

    device_ids: set[str] = set()
    device_manager = TuyaDeviceManager(api, tuya_mq)
    home_manager = TuyaHomeManager(api, tuya_mq, device_manager)
    listener = DeviceListener(hass, device_manager, device_ids)
    device_manager.add_device_listener(listener)

    hass.data[DOMAIN][entry.entry_id] = HomeAssistantTuyaData(
        device_listener=listener,
        device_manager=device_manager,
        home_manager=home_manager,
    )

    # Get devices & clean up device entities
    await hass.async_add_executor_job(home_manager.update_device_cache)
    await cleanup_device_registry(hass, device_manager)

    # Migrate old unique_ids to the new format
    async_migrate_entities_unique_ids(hass, entry, device_manager)

    # Register known device IDs
    device_registry = dr.async_get(hass)
    for device in device_manager.device_map.values():
        device_registry.async_get_or_create(
            config_entry_id=entry.entry_id,
            identifiers={(DOMAIN, device.id)},
            manufacturer="Tuya",
            name=device.name,
            model=f"{device.product_name} (unsupported)",
        )
        device_ids.add(device.id)

    hass.config_entries.async_setup_platforms(entry, PLATFORMS)
    return True
Example #4
0
    async def _init_tuya_sdk(self) -> bool:
        auth_type = AuthType(0)
        api = TuyaOpenAPI(
            self._get_region_url(self._t_region),
            self._t_apikey,
            self._t_apisecret,
            auth_type,
        )

        api.set_dev_channel("fhempy")

        response = (
            await utils.run_blocking(
                functools.partial(api.connect, self._t_username, self._t_password)
            )
            if auth_type == AuthType.CUSTOM
            else await utils.run_blocking(
                functools.partial(
                    api.connect,
                    self._t_username,
                    self._t_password,
                    self._get_countrycode(self._t_region),
                    self._t_apptype,
                )
            )
        )
        if response.get("success", False) is False:
            if response.get("code", 0) == 2406:
                await fhem.readingsSingleUpdate(
                    self.hash, "state", "Tuya project too old, create new one", 1
                )
            else:
                await fhem.readingsSingleUpdate(
                    self.hash, "state", f"failed to login: {response}", 1
                )
                self.logger.error(f"Tuya login error response: {response}")
            return False

        self.tuya_pulsar = TuyaOpenPulsar(
            self._t_apikey,
            self._t_apisecret,
            self._get_pulsar_endpoint(self._t_region),
            TuyaCloudPulsarTopic.PROD,
        )
        self.tuya_pulsar.start()

        # check if pulsar is working
        await asyncio.sleep(2)
        pulsar_connected = False
        try:
            pulsar_connected = self.tuya_pulsar.ws_app.sock.status == 101
        except Exception:
            pass

        if pulsar_connected is False:
            self.logger.error(
                "Please activate OpenPulsar: "
                + "https://developer.tuya.com/en/docs/iot/subscribe-mq?id=Kavqcrvckbh9h"
            )
            # pulsar not working
            self.tuya_pulsar.stop()
        else:
            self.logger.info("Tuya Open Pulsar connected")

        self.tuya_mq = TuyaOpenMQ(api)
        self.tuya_mq.start()

        self.device_manager = TuyaDeviceManager(api, self.tuya_mq)

        # Get device list
        self.home_manager = TuyaHomeManager(api, self.tuya_mq, self.device_manager)
        await utils.run_blocking(
            functools.partial(self.home_manager.update_device_cache)
        )
        t_cloud_setup = self

        class DeviceListener(TuyaDeviceListener):
            """Device Update Listener."""

            def __init__(self, logger) -> None:
                super().__init__()
                self.logger = logger

            def update_device(self, device: TuyaDevice):
                self.logger.debug(f"update_device received for {device.id}")
                for dev in t_cloud_setup.tuya_devices:
                    if dev.id == device.id:
                        try:
                            asyncio.run_coroutine_threadsafe(
                                dev.update(device), t_cloud_setup.fhemdev.loop
                            )
                        except Exception:
                            self.logger.exception("Failed to update device")

            def add_device(self, device: TuyaDevice):
                self.logger.info(f"add_device received for {device.id}")
                try:
                    asyncio.run_coroutine_threadsafe(
                        self.add_fhem_device(device), t_cloud_setup.fhemdev.loop
                    )
                except Exception:
                    self.logger.exception("Failed to add device")

            async def add_fhem_device(self, device: TuyaDevice):
                await t_cloud_setup._create_fhem_device(device.name, device.id)
                try:
                    self.tuya_mq.stop()
                except Exception:
                    pass
                self.tuya_mq = TuyaOpenMQ(
                    t_cloud_setup.device_manager.device_manager.api
                )
                self.tuya_mq.start()

                t_cloud_setup.device_manager.mq = self.tuya_mq
                self.tuya_mq.add_message_listener(
                    t_cloud_setup.device_manager.on_message
                )

            def remove_device(self, device_id: str):
                self.logger.info(f"remove_device received for {device_id}")

        __listener = DeviceListener(self.logger)
        self.device_manager.add_device_listener(__listener)

        def on_pulsar_message(msg):
            msg = json.loads(msg)
            status = msg.get("status", [])
            device = {"id": msg["devId"], "status": status}
            self.logger.debug(f"update_device received: {msg}")
            for dev in t_cloud_setup.tuya_devices:
                if dev.id == device["id"]:
                    try:
                        asyncio.run_coroutine_threadsafe(
                            dev.update_readings_arr(device["status"]),
                            t_cloud_setup.fhemdev.loop,
                        )
                    except Exception:
                        self.logger.exception("Failed to update device")

        self.tuya_pulsar.add_message_listener(on_pulsar_message)

        return True
Example #5
0
class tuya_cloud_setup:
    def __init__(self, logger, fhemdevice: FhemModule):
        self.logger = logger
        self.fhemdev = fhemdevice
        self.hash = fhemdevice.hash
        self._t_devicelist = []
        self._ready = False

    async def Define(self, hash, args, argsh):
        self._t_apikey = args[4]
        self._t_apisecret = args[5]
        self._t_username = args[6]
        self._t_password = args[7]
        if len(args) > 8:
            self._t_apptype = args[8]
        else:
            self._t_apptype = "smartlife"

        if len(args) > 9:
            self._t_region = args[9]
        else:
            self._t_region = "Europe"

        self.fhemdev.create_async_task(self.run_setup())

    def _get_region_url(self, region) -> str:
        for url in TUYA_ENDPOINT:
            if TUYA_ENDPOINT[url] == region:
                return url

    def _get_pulsar_endpoint(self, region):
        return "wss://mqe.tuya" + self._get_countrycode(self._t_region) + ".com:8285/"

    def _get_countrycode(self, region) -> str:
        if region == "Europe":
            return "eu"
        else:
            return "cn"

    async def run_setup(self):
        await fhem.readingsSingleUpdate(self.hash, "state", "connecting", 1)
        if await self._init_tuya_sdk() is True:
            self._ready = True
            await fhem.readingsSingleUpdate(self.hash, "state", "connected", 1)
            await self._init_devices()

    async def _init_tuya_sdk(self) -> bool:
        auth_type = AuthType(0)
        api = TuyaOpenAPI(
            self._get_region_url(self._t_region),
            self._t_apikey,
            self._t_apisecret,
            auth_type,
        )

        api.set_dev_channel("fhempy")

        response = (
            await utils.run_blocking(
                functools.partial(api.connect, self._t_username, self._t_password)
            )
            if auth_type == AuthType.CUSTOM
            else await utils.run_blocking(
                functools.partial(
                    api.connect,
                    self._t_username,
                    self._t_password,
                    self._get_countrycode(self._t_region),
                    self._t_apptype,
                )
            )
        )
        if response.get("success", False) is False:
            if response.get("code", 0) == 2406:
                await fhem.readingsSingleUpdate(
                    self.hash, "state", "Tuya project too old, create new one", 1
                )
            else:
                await fhem.readingsSingleUpdate(
                    self.hash, "state", f"failed to login: {response}", 1
                )
                self.logger.error(f"Tuya login error response: {response}")
            return False

        self.tuya_pulsar = TuyaOpenPulsar(
            self._t_apikey,
            self._t_apisecret,
            self._get_pulsar_endpoint(self._t_region),
            TuyaCloudPulsarTopic.PROD,
        )
        self.tuya_pulsar.start()

        # check if pulsar is working
        await asyncio.sleep(2)
        pulsar_connected = False
        try:
            pulsar_connected = self.tuya_pulsar.ws_app.sock.status == 101
        except Exception:
            pass

        if pulsar_connected is False:
            self.logger.error(
                "Please activate OpenPulsar: "
                + "https://developer.tuya.com/en/docs/iot/subscribe-mq?id=Kavqcrvckbh9h"
            )
            # pulsar not working
            self.tuya_pulsar.stop()
        else:
            self.logger.info("Tuya Open Pulsar connected")

        self.tuya_mq = TuyaOpenMQ(api)
        self.tuya_mq.start()

        self.device_manager = TuyaDeviceManager(api, self.tuya_mq)

        # Get device list
        self.home_manager = TuyaHomeManager(api, self.tuya_mq, self.device_manager)
        await utils.run_blocking(
            functools.partial(self.home_manager.update_device_cache)
        )
        t_cloud_setup = self

        class DeviceListener(TuyaDeviceListener):
            """Device Update Listener."""

            def __init__(self, logger) -> None:
                super().__init__()
                self.logger = logger

            def update_device(self, device: TuyaDevice):
                self.logger.debug(f"update_device received for {device.id}")
                for dev in t_cloud_setup.tuya_devices:
                    if dev.id == device.id:
                        try:
                            asyncio.run_coroutine_threadsafe(
                                dev.update(device), t_cloud_setup.fhemdev.loop
                            )
                        except Exception:
                            self.logger.exception("Failed to update device")

            def add_device(self, device: TuyaDevice):
                self.logger.info(f"add_device received for {device.id}")
                try:
                    asyncio.run_coroutine_threadsafe(
                        self.add_fhem_device(device), t_cloud_setup.fhemdev.loop
                    )
                except Exception:
                    self.logger.exception("Failed to add device")

            async def add_fhem_device(self, device: TuyaDevice):
                await t_cloud_setup._create_fhem_device(device.name, device.id)
                try:
                    self.tuya_mq.stop()
                except Exception:
                    pass
                self.tuya_mq = TuyaOpenMQ(
                    t_cloud_setup.device_manager.device_manager.api
                )
                self.tuya_mq.start()

                t_cloud_setup.device_manager.mq = self.tuya_mq
                self.tuya_mq.add_message_listener(
                    t_cloud_setup.device_manager.on_message
                )

            def remove_device(self, device_id: str):
                self.logger.info(f"remove_device received for {device_id}")

        __listener = DeviceListener(self.logger)
        self.device_manager.add_device_listener(__listener)

        def on_pulsar_message(msg):
            msg = json.loads(msg)
            status = msg.get("status", [])
            device = {"id": msg["devId"], "status": status}
            self.logger.debug(f"update_device received: {msg}")
            for dev in t_cloud_setup.tuya_devices:
                if dev.id == device["id"]:
                    try:
                        asyncio.run_coroutine_threadsafe(
                            dev.update_readings_arr(device["status"]),
                            t_cloud_setup.fhemdev.loop,
                        )
                    except Exception:
                        self.logger.exception("Failed to update device")

        self.tuya_pulsar.add_message_listener(on_pulsar_message)

        return True

    @property
    def ready(self):
        return self._ready

    def register_tuya_device(self, device):
        self._t_devicelist.append(device)

    @property
    def tuya_devices(self):
        return self._t_devicelist

    async def _create_fhem_device(self, name, device_id):
        devalias = name
        devname = name + "_" + device_id
        devname = utils.remove_umlaut(devname.replace(" ", "_").replace("-", "_"))
        device_exists = await fhem.checkIfDeviceExists(
            self.hash, "PYTHONTYPE", "tuya_cloud", "DEVICEID", device_id
        )
        if not device_exists:
            self.logger.info(
                (
                    f"create: {devname} PythonModule tuya_cloud "
                    f"{self.hash['NAME']} {device_id}"
                )
            )
            # define each device (CommandDefine ... tuya_cloud_setup_dev deviceid
            await fhem.CommandDefine(
                self.hash,
                (
                    f"{devname} PythonModule tuya_cloud "
                    f"{self.hash['NAME']} {device_id}"
                ),
            )
            await fhem.CommandAttr(self.hash, f"{devname} alias {devalias}")
            # wait for FHEM to handle CommandDefine
            await asyncio.sleep(1)

    async def _init_devices(self):
        # wait for init to complete, otherwise devices might not be available yet
        while await fhem.init_done(self.hash) == 0:
            await asyncio.sleep(3)

        # retrieve devices from device_manager and create them
        for device_id in self.device_manager.device_map:
            await self._create_fhem_device(
                self.device_manager.device_map[device_id].name, device_id
            )

    async def send_commands(self, deviceid, commands):
        await utils.run_blocking(
            functools.partial(self.device_manager.send_commands, deviceid, commands)
        )
Example #6
0
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    """Async setup hass config entry."""
    hass.data.setdefault(DOMAIN, {})

    # Project type has been renamed to auth type in the upstream Tuya IoT SDK.
    # This migrates existing config entries to reflect that name change.
    if CONF_PROJECT_TYPE in entry.data:
        data = {**entry.data, CONF_AUTH_TYPE: entry.data[CONF_PROJECT_TYPE]}
        data.pop(CONF_PROJECT_TYPE)
        hass.config_entries.async_update_entry(entry, data=data)

    auth_type = AuthType(entry.data[CONF_AUTH_TYPE])
    api = TuyaOpenAPI(
        endpoint=entry.data[CONF_ENDPOINT],
        access_id=entry.data[CONF_ACCESS_ID],
        access_secret=entry.data[CONF_ACCESS_SECRET],
        auth_type=auth_type,
    )

    api.set_dev_channel("hass")

    try:
        if auth_type == AuthType.CUSTOM:
            response = await hass.async_add_executor_job(
                api.connect, entry.data[CONF_USERNAME],
                entry.data[CONF_PASSWORD])
        else:
            response = await hass.async_add_executor_job(
                api.connect,
                entry.data[CONF_USERNAME],
                entry.data[CONF_PASSWORD],
                entry.data[CONF_COUNTRY_CODE],
                entry.data[CONF_APP_TYPE],
            )
    except requests.exceptions.RequestException as err:
        raise ConfigEntryNotReady(err) from err

    if response.get("success", False) is False:
        raise ConfigEntryNotReady(response)

    tuya_mq = TuyaOpenMQ(api)
    tuya_mq.start()

    device_ids: set[str] = set()
    device_manager = TuyaDeviceManager(api, tuya_mq)
    home_manager = TuyaHomeManager(api, tuya_mq, device_manager)
    listener = DeviceListener(hass, device_manager, device_ids)
    device_manager.add_device_listener(listener)

    hass.data[DOMAIN][entry.entry_id] = HomeAssistantTuyaData(
        device_listener=listener,
        device_manager=device_manager,
        home_manager=home_manager,
    )

    # Get devices & clean up device entities
    await hass.async_add_executor_job(home_manager.update_device_cache)
    await cleanup_device_registry(hass, device_manager)

    # Migrate old unique_ids to the new format
    async_migrate_entities_unique_ids(hass, entry, device_manager)

    # Register known device IDs
    device_registry = dr.async_get(hass)
    for device in device_manager.device_map.values():
        device_registry.async_get_or_create(
            config_entry_id=entry.entry_id,
            identifiers={(DOMAIN, device.id)},
            manufacturer="Tuya",
            name=device.name,
            model=f"{device.product_name} (unsupported)",
        )
        device_ids.add(device.id)

    await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
    return True
Example #7
0
async def _init_tuya_sdk(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    init_entry_data = entry.data
    # decrypt or encrypt entry info
    entry_data = entry_decrypt(hass, entry, init_entry_data)
    project_type = ProjectType(entry_data[CONF_PROJECT_TYPE])
    api = TuyaOpenAPI(
        entry_data[CONF_ENDPOINT],
        entry_data[CONF_ACCESS_ID],
        entry_data[CONF_ACCESS_SECRET],
        project_type,
    )

    api.set_dev_channel("hass")

    response = (
        await hass.async_add_executor_job(
            api.login, entry_data[CONF_USERNAME], entry_data[CONF_PASSWORD]
        )
        if project_type == ProjectType.INDUSTY_SOLUTIONS
        else await hass.async_add_executor_job(
            api.login,
            entry_data[CONF_USERNAME],
            entry_data[CONF_PASSWORD],
            entry_data[CONF_COUNTRY_CODE],
            entry_data[CONF_APP_TYPE],
        )
    )
    if response.get("success", False) is False:
        _LOGGER.error(f"Tuya login error response: {response}")
        return False

    tuya_mq = TuyaOpenMQ(api)
    tuya_mq.start()

    device_manager = TuyaDeviceManager(api, tuya_mq)

    # Get device list
    home_manager = TuyaHomeManager(api, tuya_mq, device_manager)
    await hass.async_add_executor_job(home_manager.update_device_cache)
    hass.data[DOMAIN][TUYA_HOME_MANAGER] = home_manager

    class DeviceListener(TuyaDeviceListener):
        """Device Update Listener."""

        def update_device(self, device: TuyaDevice):
            for ha_device in hass.data[DOMAIN][TUYA_HA_DEVICES]:
                if ha_device.tuya_device.id == device.id:
                    _LOGGER.debug(f"_update-->{self};->>{ha_device.tuya_device.status}")
                    ha_device.schedule_update_ha_state()

        def add_device(self, device: TuyaDevice):

            device_add = False

            _LOGGER.info(
                f"""add device category->{device.category}; keys->,
                {hass.data[DOMAIN][TUYA_HA_TUYA_MAP].keys()}"""
            )
            if device.category in itertools.chain(
                *hass.data[DOMAIN][TUYA_HA_TUYA_MAP].values()
            ):
                ha_tuya_map = hass.data[DOMAIN][TUYA_HA_TUYA_MAP]

                remove_hass_device(hass, device.id)

                for key, tuya_list in ha_tuya_map.items():
                    if device.category in tuya_list:
                        device_add = True
                        async_dispatcher_send(
                            hass, TUYA_DISCOVERY_NEW.format(key), [device.id]
                        )

            if device_add:
                device_manager = hass.data[DOMAIN][TUYA_DEVICE_MANAGER]
                device_manager.mq.stop()
                tuya_mq = TuyaOpenMQ(device_manager.api)
                tuya_mq.start()

                device_manager.mq = tuya_mq
                tuya_mq.add_message_listener(device_manager.on_message)

        def remove_device(self, device_id: str):
            _LOGGER.info(f"tuya remove device:{device_id}")
            remove_hass_device(hass, device_id)

    __listener = DeviceListener()
    hass.data[DOMAIN][TUYA_MQTT_LISTENER] = __listener
    device_manager.add_device_listener(__listener)
    hass.data[DOMAIN][TUYA_DEVICE_MANAGER] = device_manager

    # Clean up device entities
    await cleanup_device_registry(hass)

    _LOGGER.info(f"init support type->{TUYA_SUPPORT_HA_TYPE}")

    for platform in TUYA_SUPPORT_HA_TYPE:
        _LOGGER.info(f"tuya async platform-->{platform}")
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setup(entry, platform)
        )
        hass.data[DOMAIN][TUYA_SETUP_PLATFORM].add(platform)

    return True
Example #8
0
TUYA_LOGGER.setLevel(logging.DEBUG)
# Init
openapi = TuyaOpenAPI(ENDPOINT, ACCESS_ID, ACCESS_KEY, AuthType.CUSTOM)

openapi.connect(USERNAME, PASSWORD)
openmq = TuyaOpenMQ(openapi)
openmq.start()

print("device test-> ", openapi.token_info.uid)
# Get device list
# assetManager = TuyaAssetManager(openapi)
# devIds = assetManager.getDeviceList(ASSET_ID)

# Update device status
deviceManager = TuyaDeviceManager(openapi, openmq)

homeManager = TuyaHomeManager(openapi, openmq, deviceManager)
homeManager.update_device_cache()
# # deviceManager.updateDeviceCaches(devIds)
# device = deviceManager.deviceMap.get(DEVICE_ID)


class tuyaDeviceListener(TuyaDeviceListener):
    def update_device(self, device: TuyaDevice):
        print("_update-->", device)

    def add_device(self, device: TuyaDevice):
        print("_add-->", device)

    def remove_device(self, device_id: str):