예제 #1
0
def test_unavailable_device_info_raises(mocker):
    send = mocker.patch("miio.Device.send", side_effect=PayloadDecodeException)
    d = Device("127.0.0.1", "68ffffffffffffffffffffffffffffff")

    with pytest.raises(DeviceInfoUnavailableException):
        d.info()

    assert send.call_count == 1
예제 #2
0
def test_unavailable_device_info_raises(mocker):
    """Make sure custom exception is raised if the info payload is invalid."""
    send = mocker.patch("miio.Device.send", side_effect=PayloadDecodeException)
    d = Device("127.0.0.1", "68ffffffffffffffffffffffffffffff")

    with pytest.raises(DeviceInfoUnavailableException):
        d.info()

    assert send.call_count == 1
예제 #3
0
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
    """Set up the sensor from config."""
    from miio import Device, DeviceException

    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}

    host = config.get(CONF_HOST)
    token = config.get(CONF_TOKEN)

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    try:
        miio_device = Device(host, token)
        device_info = miio_device.info()
        model = device_info.model
        _LOGGER.info(
            "%s %s %s detected",
            model,
            device_info.firmware_version,
            device_info.hardware_version,
        )

        device = XiaomiMiioGenericDevice(miio_device, config, device_info)
    except DeviceException:
        raise PlatformNotReady

    hass.data[DATA_KEY][host] = device
    async_add_devices([device], update_before_add=True)

    @asyncio.coroutine
    def async_service_handler(service):
        """Map services to methods on XiaomiMiioDevice."""
        method = SERVICE_TO_METHOD.get(service.service)
        params = {
            key: value for key, value in service.data.items() if key != ATTR_ENTITY_ID
        }
        entity_ids = service.data.get(ATTR_ENTITY_ID)
        if entity_ids:
            devices = [
                device
                for device in hass.data[DATA_KEY].values()
                if device.entity_id in entity_ids
            ]
        else:
            devices = hass.data[DATA_KEY].values()

        update_tasks = []
        for device in devices:
            yield from getattr(device, method["method"])(**params)
            update_tasks.append(device.async_update_ha_state(True))

        if update_tasks:
            yield from asyncio.wait(update_tasks, loop=hass.loop)

    for service in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[service].get("schema", SERVICE_SCHEMA)
        hass.services.async_register(
            DOMAIN, service, async_service_handler, schema=schema
        )
예제 #4
0
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
    from miio import Device, DeviceException

    host = config.get(CONF_HOST)
    token = config.get(CONF_TOKEN)
    baseUrl = config.get(CONF_BASEURL)
    basePath = config.get(CONF_BASEPATH)
    apiKey = config.get(CONF_APIKEY)
    secretKey = config.get(CONF_SECRETKEY)
    speed = config.get(CONF_SPEED, 5)
    pitch = config.get(CONF_PITCH, 5)
    volume = config.get(CONF_VOLUME, 5)
    person = config.get(CONF_PERSON, 0)
    notify = config.get(CONF_NOTIFY, False)
    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])
    device = Device(host, token, lazy_discover=False)
    try:
        device_info = device.info()
        model = device_info.model
        unique_id = "{}-{}".format(model, device_info.mac_address)
        _LOGGER.info("%s %s %s detected", model, device_info.firmware_version,
                     device_info.hardware_version)
    except DeviceException as ex:
        _LOGGER.error("Device unavailable or token incorrect: %s", ex)
        raise PlatformNotReady
    friendly_name = config.get(CONF_NAME,
                               "miio_miio_acpartner_" + host.replace('.', '_'))
    xiaomi_miio_radio = XiaomiMiioRadio(friendly_name, device, unique_id,
                                        apiKey, secretKey, speed, pitch,
                                        volume, person, baseUrl, basePath,
                                        notify)
    async_add_devices([xiaomi_miio_radio])
예제 #5
0
 async def async_step_user(self, user_input=None):
     errors = {}
     if user_input is not None:
         if user_input.get(CONF_HOST):
             self.host = user_input[CONF_HOST]
         token = user_input.get(CONF_TOKEN)
         device = MiioDevice(self.host, token)
         try:
             info = device.info()
         except DeviceException:
             info = None
             errors['base'] = 'cannot_connect'
         _LOGGER.debug('Xiaomi Miot async_step_user %s', {
             'user_input': user_input,
             'info': info,
             'errors': errors,
         })
         if info is not None:
             unique_id = format_mac(info.mac_address)
             await self.async_set_unique_id(unique_id)
             self._abort_if_unique_id_configured()
             if not user_input.get(CONF_MODEL):
                 user_input[CONF_MODEL] = str(info.model or '')
             user_input['miio_info'] = dict(info.raw or {})
             return self.async_create_entry(
                 title=user_input.get(CONF_NAME),
                 data=user_input,
             )
     return self.async_show_form(
         step_id='user',
         data_schema=MIIO_CONFIG_SCHEMA,
         errors=errors,
     )
예제 #6
0
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
    """Set up the sensor from config."""
    from miio import Device, DeviceException

    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}

    host = config.get(CONF_HOST)
    token = config.get(CONF_TOKEN)

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    try:
        miio_device = Device(host, token)
        device_info = miio_device.info()
        model = device_info.model
        _LOGGER.info(
            "%s %s %s detected",
            model,
            device_info.firmware_version,
            device_info.hardware_version,
        )

        device = XiaomiHeatcoldDevice(miio_device, config, device_info)
    except DeviceException:
        raise PlatformNotReady

    hass.data[DATA_KEY][host] = device
    async_add_devices([device], update_before_add=True)
예제 #7
0
def setup_platform(hass, config, async_add_devices, discovery_info=None):
    """Perform the setup for Xiaomi heaters."""
    from miio import Device, DeviceException
    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)

    _LOGGER.info("Initializing Xiaomi heaters with host %s (token %s...)",
                 host, token[:5])

    try:
        device = Device(host, token)

        device_info = device.info()
        model = device_info.model
        unique_id = "{}-{}".format(model, device_info.mac_address)
        _LOGGER.info("%s %s %s detected", model, device_info.firmware_version,
                     device_info.hardware_version)
    except DeviceException:
        _LOGGER.exception('Fail to setup Xiaomi heater')
        raise PlatformNotReady
    miHeater = MiHeater(device, name, unique_id, hass)
    hass.data[DATA_KEY][host] = miHeater
    async_add_devices([miHeater], update_before_add=True)

    async def async_service_handler(service):
        """Map services to methods on XiaomiAirConditioningCompanion."""
        method = SERVICE_TO_METHOD.get(service.service)
        params = {
            key: value
            for key, value in service.data.items() if key != ATTR_ENTITY_ID
        }
        entity_ids = service.data.get(ATTR_ENTITY_ID)
        if entity_ids:
            devices = [
                device for device in hass.data[DATA_KEY].values()
                if device.entity_id in entity_ids
            ]
        else:
            devices = hass.data[DATA_KEY].values()

        update_tasks = []
        for device in devices:
            if not hasattr(device, method['method']):
                continue
            await getattr(device, method['method'])(**params)
            update_tasks.append(device.async_update_ha_state(True))

        if update_tasks:
            await asyncio.wait(update_tasks, loop=hass.loop)

    for service in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[service].get('schema', SERVICE_SCHEMA)
        hass.services.async_register(DOMAIN,
                                     service,
                                     async_service_handler,
                                     schema=schema)
예제 #8
0
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
    """Set up the Xiaomi Gateway platform."""
    from miio import Device, DeviceException

    host = config.get(CONF_HOST)
    token = config.get(CONF_TOKEN)

    # Create handler
    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    # The Chuang Mi IR Radio Controller wants to be re-discovered every
    # 5 minutes. As long as polling is disabled the device should be
    # re-discovered (lazy_discover=False) in front of every command.
    device = Device(host, token, lazy_discover=False)

    # Check that we can communicate with device.
    try:
        device_info = device.info()
        model = device_info.model
        unique_id = "{}-{}".format(model, device_info.mac_address)
        _LOGGER.info("%s %s %s detected",
                     model,
                     device_info.firmware_version,
                     device_info.hardware_version)
    except DeviceException as ex:
        _LOGGER.error("Device unavailable or token incorrect: %s", ex)
        raise PlatformNotReady
    friendly_name = config.get(CONF_NAME, "miio_radio_" + host.replace('.', '_'))
    xiaomi_miio_radio = XiaomiMiioRadio(friendly_name, device, unique_id)
    async_add_devices([xiaomi_miio_radio])
예제 #9
0
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
    """Set up the switch from config."""
    from miio import Device, DeviceException

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)
    model = config.get(CONF_MODEL)

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    devices = []

    if model is None:
        try:
            miio_device = Device(host, token)
            device_info = miio_device.info()
            model = device_info.model
            _LOGGER.info("%s %s %s detected",
                         model,
                         device_info.firmware_version,
                         device_info.hardware_version)
        except DeviceException:
            raise PlatformNotReady

    if model in ['chuangmi.plug.v1']:
        from miio import PlugV1
        plug = PlugV1(host, token)

        # The device has two switchable channels (mains and a USB port).
        # A switch device per channel will be created.
        for channel_usb in [True, False]:
            device = ChuangMiPlugV1Switch(
                name, plug, model, channel_usb)
            devices.append(device)

    elif model in ['qmi.powerstrip.v1',
                   'zimi.powerstrip.v2']:
        from miio import PowerStrip
        plug = PowerStrip(host, token)
        device = XiaomiPowerStripSwitch(name, plug, model)
        devices.append(device)
    elif model in ['chuangmi.plug.m1',
                   'chuangmi.plug.v2']:
        from miio import Plug
        plug = Plug(host, token)
        device = XiaomiPlugGenericSwitch(name, plug, model)
        devices.append(device)
    else:
        _LOGGER.error(
            'Unsupported device found! Please create an issue at '
            'https://github.com/rytilahti/python-miio/issues '
            'and provide the following data: %s', model)
        return False

    async_add_devices(devices, update_before_add=True)
예제 #10
0
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Perform the setup for Xiaomi heaters."""
    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)
    model = config.get(CONF_MODEL)

    _LOGGER.info("Initializing Xiaomi heaters with host %s (token %s...)",
                 host, token[:5])

    devices = []
    unique_id = None

    try:
        device = Device(host, token)
        device_info = device.info()

        if model is None:

            model = device_info.model
            DEVICE_MODEL = model

        unique_id = "{}-{}".format(model, device_info.mac_address)
        _LOGGER.warning("%s %s %s detected", model,
                        device_info.firmware_version,
                        device_info.hardware_version)
        miHeater = MiHeater(device, name, model, unique_id, hass)
        devices.append(miHeater)
        add_devices(devices)

        async def set_room_temp(service):
            """Set room temp."""

            if DEVICE_MODEL == "zhimi.heater.mc2":
                aux = device.raw_command('get_properties', [{
                    "siid": 2,
                    "piid": 5
                }])
            elif DEVICE_MODEL == "zhimi.heater.zb1" or DEVICE_MODEL == "zhimi.heater.za2":
                aux = device.raw_command('get_properties', [{
                    "siid": 2,
                    "piid": 6
                }])
            else:
                _LOGGER.exception('Unsupported model: %s', DEVICE_MODEL)

            temperature = aux[0]["value"]
            await miHeater.async_set_temperature(temperature)

        hass.services.async_register(DOMAIN,
                                     SERVICE_SET_ROOM_TEMP,
                                     set_room_temp,
                                     schema=SET_ROOM_TEMP_SCHEMA)
    except DeviceException:
        _LOGGER.exception('Fail to setup Xiaomi heater')
        raise PlatformNotReady
예제 #11
0
def is_gw3(host: str, token: str) -> Optional[str]:
    try:
        device = Device(host, token)
        info = device.info()
        if info.model != 'lumi.gateway.mgl03':
            raise Exception(f"Wrong device model: {info.model}")
    except Exception as e:
        return str(e)

    return None
    def update(event_time):
        """Get the latest data and updates the states."""
        try:
            miio_device = Device(host, token)

            run_status = miio_device.send('get_prop', ["run_status"])[0]
            work_status = miio_device.send('get_prop', ["work_status"])[0]
            #warm_data     =  miio_device.send('get_prop', ["warm_data"])[0]
            last_time = miio_device.send('get_prop', ["last_time"])[0]
            last_temp = miio_device.send('get_prop', ["last_temp"])[0]
            curr_tempe = miio_device.send('get_prop', ["curr_tempe"])[0]
            # work_temps    =  miio_device.send('get_prop', ["work_temps"])[0]
            mode = miio_device.send('get_prop', ["mode"])[0]  #模式
            heat_power = miio_device.send('get_prop', ["heat_power"])[0]  #功率
            warm_time = miio_device.send('get_prop', ["warm_time"])[0]  #保温时间
            cook_time = miio_device.send('get_prop', ["cook_time"])[0]  #蒸煮时间
            left_time = miio_device.send('get_prop', ["left_time"])[0]  #剩余时间
            cook_status = miio_device.send('get_prop',
                                           ["cook_status"])[0]  #蒸煮状态
            cooked_time = miio_device.send('get_prop', ["cooked_time"])[0]
            voice = miio_device.send('get_prop', ["voice"])[0]
            stand_top_num = miio_device.send('get_prop', ["stand_top_num"])[0]
            #mode_sort     =  miio_device.send('get_prop', ["mode_sort"])[0]

            __state_attrs = {
                "run_status": AVAILABLE_RUN_STATUS[int(run_status)],
                "mode": AVAILABLE_MODE[int(mode)],
                "last_time": last_time,
                "last_temp": last_temp,
                "curr_tempe": curr_tempe,
                # "work_temps":work_temps,
                "heat_power": heat_power,
                "warm_time": warm_time,
                "cook_time": cook_time,
                "left_time": left_time,
                "cook_status": cook_status,
                "cooked_time": cooked_time,
                "voice": voice,
                "stand_top_num": stand_top_num,
                #"mode_sort":mode_sort,
                #"warm_data":warm_data,
                "friendly_name": name
            }

            unique_id = "{}_{}".format(
                "xiaomi",
                miio_device.info().mac_address.replace(':', ''))
            entityid = "{}.{}".format(DOMAIN, unique_id)
            hass.states.set(entityid, AVAILABLE_STATE[int(work_status)],
                            __state_attrs)

        except DeviceException:
            _LOGGER.exception('Fail to get_prop from XiaomiHealthPot')
            raise PlatformNotReady
async def async_setup_platform(hass,
                               config,
                               async_add_entities,
                               discovery_info=None):
    """Set up the Xiaomi Whale Smart Toilet device platform."""
    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)
    model = config.get(CONF_MODEL)

    # Create handler
    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    try:
        miio_device = Device(host, token)
        device_info = miio_device.info()
        model = device_info.model or model or MODEL_TOILETLID_XJX_TOILET_PRO
        unique_id = "{}-{}".format(model, device_info.mac_address)
    except DeviceException:
        raise PlatformNotReady

    toiletlid = Toiletlid(host, token, model=model)
    device = ToiletlidEntity(name, toiletlid, model, unique_id)
    hass.data[DATA_KEY][host] = device

    async_add_entities([device], update_before_add=True)

    async def async_service_handler(service):
        """Map services to methods on Xiaomi Whale Smart Toilet."""
        method = SERVICE_TO_METHOD.get(service.service)
        params = service.data.copy()
        entity_ids = params.pop(ATTR_ENTITY_ID, hass.data[DATA_KEY].values())
        update_tasks = []

        for device in filter(lambda x: x.entity_id in entity_ids,
                             hass.data[DATA_KEY].values()):
            if not hasattr(device, method["method"]):
                continue
            await getattr(device, method["method"])(**params)
            update_tasks.append(device.async_update_ha_state(True))

        if update_tasks:
            await asyncio.wait(update_tasks)

    for toiletlid_service in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[toiletlid_service].get(
            "schema", TOILETLID_SERVICE_SCHEMA)
        hass.services.async_register(DOMAIN,
                                     toiletlid_service,
                                     async_service_handler,
                                     schema=schema)
예제 #14
0
def setup(hass, config):
    """初始化小米净水器组件"""

    if DOMAIN not in hass.data:
        hass.data[DOMAIN] = {}

    host = config[DOMAIN][CONF_HOST]
    token = config[DOMAIN][CONF_TOKEN]
    name = config[DOMAIN][CONF_NAME]
    model = config[DOMAIN].get(CONF_MODEL)
    scan_interval = config[DOMAIN][CONF_SCAN_INTERVAL]

    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}
        hass.data[DATA_KEY][host] = {}

    try:
        miio_device = Device(host, token)
        device_info = miio_device.info()
        model = device_info.model
        _LOGGER.info("发现净水器设备,型号[%s],软件版本[%s],硬件版本[%s]", model,
                     device_info.firmware_version,
                     device_info.hardware_version)
    except DeviceException:
        raise PlatformNotReady

    if model in SUPPORTED_MODELS:
        water_purifier = MiWaterPurifier(miio_device, name)
        _LOGGER.info("实例化小米净水器[%s]", name)
        hass.data[DOMAIN][host] = water_purifier
        for component in ['sensor']:
            discovery.load_platform(hass, component, DOMAIN, {}, config)
    else:
        _LOGGER.error("未支持设备型号[%s]", model)
        return False

    def update(event_time):
        """更新设备状态"""
        try:
            water_purifier.update()
            state = water_purifier.state
            hass.data[DATA_KEY][host][DATA_STATE] = state
            dispatcher_send(hass, '{}_updated'.format(DOMAIN), host)
        except DeviceException as ex:
            dispatcher_send(hass, '{}_unavailable'.format(DOMAIN), host)
            _LOGGER.error("获取净化器状态时异常[%s]", ex)

    update(utcnow())
    track_time_interval(hass, update, scan_interval)

    return True
예제 #15
0
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
    """Set up the light from config."""
    from miio import Device, DeviceException

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    devices = []
    try:
        light = Device(host, token)
        device_info = light.info()
        _LOGGER.info("%s %s %s initialized",
                     device_info.model,
                     device_info.firmware_version,
                     device_info.hardware_version)

        if device_info.model == 'philips.light.sread1':
            from miio import PhilipsEyecare
            light = PhilipsEyecare(host, token)
            device = XiaomiPhilipsEyecareLamp(name, light, device_info)
            devices.append(device)
        elif device_info.model == 'philips.light.ceiling':
            from miio import Ceil
            light = Ceil(host, token)
            device = XiaomiPhilipsCeilingLamp(name, light, device_info)
            devices.append(device)
        elif device_info.model == 'philips.light.bulb':
            from miio import PhilipsBulb
            light = PhilipsBulb(host, token)
            device = XiaomiPhilipsLightBall(name, light, device_info)
            devices.append(device)
        else:
            _LOGGER.error(
                'Unsupported device found! Please create an issue at '
                'https://github.com/rytilahti/python-miio/issues '
                'and provide the following data: %s', device_info.model)

    except DeviceException:
        raise PlatformNotReady

    async_add_devices(devices, update_before_add=True)
예제 #16
0
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
    """Set up the light from config."""
    from miio import Device, DeviceException

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    devices = []
    try:
        light = Device(host, token)
        device_info = light.info()
        _LOGGER.info("%s %s %s initialized", device_info.model,
                     device_info.firmware_version,
                     device_info.hardware_version)

        if device_info.model == 'philips.light.sread1':
            from miio import PhilipsEyecare
            light = PhilipsEyecare(host, token)
            device = XiaomiPhilipsEyecareLamp(name, light, device_info)
            devices.append(device)
        elif device_info.model == 'philips.light.ceiling':
            from miio import Ceil
            light = Ceil(host, token)
            device = XiaomiPhilipsCeilingLamp(name, light, device_info)
            devices.append(device)
        elif device_info.model == 'philips.light.bulb':
            from miio import PhilipsBulb
            light = PhilipsBulb(host, token)
            device = XiaomiPhilipsLightBall(name, light, device_info)
            devices.append(device)
        else:
            _LOGGER.error(
                'Unsupported device found! Please create an issue at '
                'https://github.com/rytilahti/python-miio/issues '
                'and provide the following data: %s', device_info.model)

    except DeviceException:
        raise PlatformNotReady

    async_add_devices(devices, update_before_add=True)
예제 #17
0
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Perform the setup for Xiaomi heaters."""
    from miio import Device, DeviceException

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)

    _LOGGER.info("Initializing Xiaomi heaters with host %s (token %s...)",
                 host, token[:5])

    devices = []
    unique_id = None

    try:
        device = Device(host, token)

        device_info = device.info()
        model = device_info.model
        unique_id = "{}-{}".format(model, device_info.mac_address)
        _LOGGER.info("%s %s %s detected", model, device_info.firmware_version,
                     device_info.hardware_version)
        miHeater = MiHeater(device, name, unique_id, hass)
        devices.append(miHeater)
        add_devices(devices)

        async def set_room_temp(service):
            """Set room temp."""
            temperature = service.data.get('temperature')
            await miHeater.async_set_temperature(temperature)

        hass.services.async_register(DOMAIN,
                                     SERVICE_SET_ROOM_TEMP,
                                     set_room_temp,
                                     schema=SET_ROOM_TEMP_SCHEMA)
    except DeviceException:
        _LOGGER.exception('Fail to setup Xiaomi heater')
        raise PlatformNotReady
예제 #18
0
async def async_setup_platform(hass, config, async_add_entities,
                               discovery_info=None):
    """Set up the switch from config."""
    from miio import Device, DeviceException
    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)
    model = config.get(CONF_MODEL)

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    devices = []
    unique_id = None

    if model is None:
        try:
            miio_device = Device(host, token)
            device_info = miio_device.info()
            model = device_info.model
            unique_id = "{}-{}".format(model, device_info.mac_address)
            _LOGGER.info("%s %s %s detected",
                         model,
                         device_info.firmware_version,
                         device_info.hardware_version)
        except DeviceException:
            raise PlatformNotReady

    if model in ['chuangmi.plug.v1', 'chuangmi.plug.v3']:
        from miio import ChuangmiPlug
        plug = ChuangmiPlug(host, token, model=model)

        # The device has two switchable channels (mains and a USB port).
        # A switch device per channel will be created.
        for channel_usb in [True, False]:
            device = ChuangMiPlugSwitch(
                name, plug, model, unique_id, channel_usb)
            devices.append(device)
            hass.data[DATA_KEY][host] = device

    elif model in ['qmi.powerstrip.v1', 'zimi.powerstrip.v2']:
        from miio import PowerStrip
        plug = PowerStrip(host, token, model=model)
        device = XiaomiPowerStripSwitch(name, plug, model, unique_id)
        devices.append(device)
        hass.data[DATA_KEY][host] = device
    elif model in ['chuangmi.plug.m1', 'chuangmi.plug.v2']:
        from miio import ChuangmiPlug
        plug = ChuangmiPlug(host, token, model=model)
        device = XiaomiPlugGenericSwitch(name, plug, model, unique_id)
        devices.append(device)
        hass.data[DATA_KEY][host] = device
    else:
        _LOGGER.error(
            'Unsupported device found! Please create an issue at '
            'https://github.com/rytilahti/python-miio/issues '
            'and provide the following data: %s', model)
        return False

    async_add_entities(devices, update_before_add=True)

    async def async_service_handler(service):
        """Map services to methods on XiaomiPlugGenericSwitch."""
        method = SERVICE_TO_METHOD.get(service.service)
        params = {key: value for key, value in service.data.items()
                  if key != ATTR_ENTITY_ID}
        entity_ids = service.data.get(ATTR_ENTITY_ID)
        if entity_ids:
            devices = [device for device in hass.data[DATA_KEY].values() if
                       device.entity_id in entity_ids]
        else:
            devices = hass.data[DATA_KEY].values()

        update_tasks = []
        for device in devices:
            if not hasattr(device, method['method']):
                continue
            await getattr(device, method['method'])(**params)
            update_tasks.append(device.async_update_ha_state(True))

        if update_tasks:
            await asyncio.wait(update_tasks, loop=hass.loop)

    for plug_service in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[plug_service].get('schema', SERVICE_SCHEMA)
        hass.services.async_register(
            DOMAIN, plug_service, async_service_handler, schema=schema)
def setup(hass, config):
    """Set up the platform from config."""
    from miio import Device, DeviceException
    if DOMAIN not in hass.data:
        hass.data[DOMAIN] = {}

    host = config[DOMAIN][CONF_HOST]
    token = config[DOMAIN][CONF_TOKEN]
    name = config[DOMAIN][CONF_NAME]
    model = config[DOMAIN].get(CONF_MODEL)
    scan_interval = config[DOMAIN][CONF_SCAN_INTERVAL]

    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}
        hass.data[DATA_KEY][host] = {}

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    if model is None:
        try:
            miio_device = Device(host, token)
            device_info = miio_device.info()
            model = device_info.model
            _LOGGER.info("%s %s %s detected", model,
                         device_info.firmware_version,
                         device_info.hardware_version)
        except DeviceException:
            raise PlatformNotReady

    if model in SUPPORTED_MODELS:
        from miio import Cooker
        cooker = Cooker(host, token)

        hass.data[DOMAIN][host] = cooker

        for component in ['sensor']:
            discovery.load_platform(hass, component, DOMAIN, {}, config)

    else:
        _LOGGER.error(
            'Unsupported device found! Please create an issue at '
            'https://github.com/syssi/xiaomi_cooker/issues '
            'and provide the following data: %s', model)
        return False

    def update(event_time):
        """Update device status."""
        from miio.cooker import OperationMode

        try:
            state = cooker.status()
            _LOGGER.debug("Got new state: %s", state)
            hass.data[DATA_KEY][host][DATA_STATE] = state

            if state.mode in [
                    OperationMode.Running, OperationMode.AutoKeepWarm
            ]:
                hass.data[DATA_KEY][host][
                    DATA_TEMPERATURE_HISTORY] = cooker.get_temperature_history(
                    )

            dispatcher_send(hass, '{}_updated'.format(DOMAIN), host)

        except DeviceException as ex:
            dispatcher_send(hass, '{}_unavailable'.format(DOMAIN), host)
            _LOGGER.error("Got exception while fetching the state: %s", ex)

    update(utcnow())
    track_time_interval(hass, update, scan_interval)

    def start_service(call):
        """Service to start cooking."""
        profile = call.data.get(ATTR_PROFILE)
        cooker.start(profile)

    def stop_service(call):
        """Service to stop cooking."""
        cooker.stop()

    hass.services.register(DOMAIN,
                           SERVICE_START,
                           start_service,
                           schema=SERVICE_SCHEMA_START)

    hass.services.register(DOMAIN,
                           SERVICE_STOP,
                           stop_service,
                           schema=SERVICE_SCHEMA)

    return True
예제 #20
0
파일: light.py 프로젝트: crazyfish1111/home
async def async_setup_platform(hass, config, async_add_entities,
                               discovery_info=None):
    """Set up the light from config."""
    from miio import Device, DeviceException
    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)
    model = config.get(CONF_MODEL)

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    devices = []
    unique_id = None

    if model is None:
        try:
            miio_device = Device(host, token)
            device_info = miio_device.info()
            model = device_info.model
            unique_id = "{}-{}".format(model, device_info.mac_address)
            _LOGGER.info("%s %s %s detected",
                         model,
                         device_info.firmware_version,
                         device_info.hardware_version)
        except DeviceException:
            raise PlatformNotReady

    if model == 'philips.light.sread1':
        from miio import PhilipsEyecare
        light = PhilipsEyecare(host, token)
        primary_device = XiaomiPhilipsEyecareLamp(
            name, light, model, unique_id)
        devices.append(primary_device)
        hass.data[DATA_KEY][host] = primary_device

        secondary_device = XiaomiPhilipsEyecareLampAmbientLight(
            name, light, model, unique_id)
        devices.append(secondary_device)
        # The ambient light doesn't expose additional services.
        # A hass.data[DATA_KEY] entry isn't needed.
    elif model in ['philips.light.ceiling', 'philips.light.zyceiling']:
        from miio import Ceil
        light = Ceil(host, token)
        device = XiaomiPhilipsCeilingLamp(name, light, model, unique_id)
        devices.append(device)
        hass.data[DATA_KEY][host] = device
    elif model == 'philips.light.moonlight':
        from miio import PhilipsMoonlight
        light = PhilipsMoonlight(host, token)
        device = XiaomiPhilipsMoonlightLamp(name, light, model, unique_id)
        devices.append(device)
        hass.data[DATA_KEY][host] = device
    elif model in ['philips.light.bulb',
                   'philips.light.candle',
                   'philips.light.candle2',
                   'philips.light.downlight']:
        from miio import PhilipsBulb
        light = PhilipsBulb(host, token)
        device = XiaomiPhilipsBulb(name, light, model, unique_id)
        devices.append(device)
        hass.data[DATA_KEY][host] = device
    elif model == 'philips.light.mono1':
        from miio import PhilipsBulb
        light = PhilipsBulb(host, token)
        device = XiaomiPhilipsGenericLight(name, light, model, unique_id)
        devices.append(device)
        hass.data[DATA_KEY][host] = device
    else:
        _LOGGER.error(
            'Unsupported device found! Please create an issue at '
            'https://github.com/syssi/philipslight/issues '
            'and provide the following data: %s', model)
        return False

    async_add_entities(devices, update_before_add=True)

    async def async_service_handler(service):
        """Map services to methods on Xiaomi Philips Lights."""
        method = SERVICE_TO_METHOD.get(service.service)
        params = {key: value for key, value in service.data.items()
                  if key != ATTR_ENTITY_ID}
        entity_ids = service.data.get(ATTR_ENTITY_ID)
        if entity_ids:
            target_devices = [dev for dev in hass.data[DATA_KEY].values()
                              if dev.entity_id in entity_ids]
        else:
            target_devices = hass.data[DATA_KEY].values()

        update_tasks = []
        for target_device in target_devices:
            if not hasattr(target_device, method['method']):
                continue
            await getattr(target_device, method['method'])(**params)
            update_tasks.append(target_device.async_update_ha_state(True))

        if update_tasks:
            await asyncio.wait(update_tasks, loop=hass.loop)

    for xiaomi_miio_service in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[xiaomi_miio_service].get(
            'schema', XIAOMI_MIIO_SERVICE_SCHEMA)
        hass.services.async_register(
            DOMAIN, xiaomi_miio_service, async_service_handler, schema=schema)
예제 #21
0
class Gateway3(Thread):
    devices: dict = None
    updates: dict = None
    setups: dict = None

    log = None

    def __init__(self, host: str, token: str):
        super().__init__(daemon=True)

        self.host = host
        self.miio = Device(host, token)

        self.mqtt = Client()
        self.mqtt.on_connect = self.on_connect
        self.mqtt.on_disconnect = self.on_disconnect
        self.mqtt.on_message = self.on_message
        self.mqtt.connect_async(host)

        if isinstance(self.log, str):
            self.log = utils.get_logger(self.log)

    @property
    def device(self):
        return self.devices['lumi.0']

    def add_update(self, did: str, handler):
        """Add handler to device update event."""
        if self.updates is None:
            self.updates = {}
        self.updates.setdefault(did, []).append(handler)

    def add_setup(self, domain: str, handler):
        """Add hass device setup funcion."""
        if self.setups is None:
            self.setups = {}
        self.setups[domain] = handler

    def run(self):
        """Main loop"""
        while self.devices is None:
            if self._miio_connect():
                devices = self._get_devices1()
                if devices:
                    self.setup_devices(devices)
                # else:
                #     self._enable_telnet()
            else:
                time.sleep(30)

        while True:
            if self._mqtt_connect():
                self.mqtt.loop_forever()

            elif self._miio_connect() and self._enable_telnet():
                self._enable_mqtt()

            else:
                _LOGGER.debug("sleep 30")
                time.sleep(30)

    def _mqtt_connect(self) -> bool:
        try:
            self.mqtt.reconnect()
            return True
        except:
            return False

    def _miio_connect(self) -> bool:
        try:
            self.miio.send_handshake()
            return True
        except:
            return False

    def _get_devices1(self) -> Optional[list]:
        """Load devices via miio protocol."""
        _LOGGER.debug(f"{self.host} | Read devices")
        try:
            devices = {}

            # endless loop protection
            for _ in range(16):
                # load only 8 device per part
                part = self.miio.send('get_device_list', retry_count=10)
                if len(part) == 0:
                    return []

                for item in part:
                    devices[item['num']] = {
                        'did': item['did'],
                        'mac': f"0x{item['did'][5:]}",
                        'model': item['model'],
                    }

                if part[0]['total'] == len(devices):
                    break

            devices = list(devices.values())
            for device in devices:
                desc = utils.get_device(device['model'])
                # skip unknown model
                if desc is None:
                    continue
                # get xiaomi param names
                params = [p[1] for p in desc['params'] if p[1] is not None]
                # skip if don't have retain params
                if not params:
                    continue
                # load param values
                values = self.miio.send('get_device_prop',
                                        [device['did']] + params)
                # get hass param names
                params = [p[2] for p in desc['params'] if p[1] is not None]

                data = dict(zip(params, values))
                # fix some param values
                for k, v in data.items():
                    if k in ('temperature', 'humidity'):
                        data[k] = v / 100.0
                    elif v == 'on':
                        data[k] = 1
                    elif v == 'off':
                        data[k] = 0

                device['init'] = data

            device = self.miio.info()
            devices.append({
                'did': 'lumi.0',
                'mac': device.mac_address,  # wifi mac!!!
                'model': device.model
            })

            return devices

        except Exception as e:
            return None

    def _get_devices2(self) -> Optional[list]:
        """Load device list via Telnet.

        Device desc example:
          mac: '0x158d0002c81234'
          shortId: '0x0691'
          manuCode: '0x115f'
          model: 'lumi.sensor_ht'
          did: 'lumi.158d0002c81234'
          devType: 0
          appVer: 2
          hardVer: 0
          devID: 770
          status: 0
          model_ver: 2
        """
        _LOGGER.debug(f"{self.host} | Read devices")
        try:
            telnet = Telnet(self.host)
            telnet.read_until(b"login: "******"admin\r\n")
            telnet.read_until(b'\r\n# ')  # skip greeting

            telnet.write(b"cat /data/zigbee/coordinator.info\r\n")
            telnet.read_until(b'\r\n')  # skip command
            raw = telnet.read_until(b'# ')
            device = json.loads(raw[:-2])
            device.update({
                'did': 'lumi.0',
                'model': 'lumi.gateway.mgl03',
                'host': self.host
            })

            devices = [device]

            telnet.write(b"cat /data/zigbee/device.info\r\n")
            telnet.read_until(b'\r\n')  # skip command
            raw = telnet.read_until(b'# ')
            raw = json.loads(raw[:-2])
            devices += raw['devInfo']
            telnet.close()

            return devices
        except Exception as e:
            _LOGGER.exception(f"Can't read devices: {e}")
            return None

    def _enable_telnet(self):
        _LOGGER.debug(f"{self.host} | Try enable telnet")
        try:
            resp = self.miio.send("enable_telnet_service")
            return resp[0] == 'ok'
        except Exception as e:
            _LOGGER.exception(f"Can't enable telnet: {e}")
            return False

    def _enable_mqtt(self):
        _LOGGER.debug(f"{self.host} | Try run public MQTT")
        try:
            telnet = Telnet(self.host)
            telnet.read_until(b"login: "******"admin\r\n")
            telnet.read_very_eager()  # skip response
            telnet.write(b"killall mosquitto\r\n")
            telnet.read_very_eager()  # skip response
            telnet.write(b"mosquitto -d\r\n")
            telnet.read_very_eager()  # skip response
            time.sleep(1)
            telnet.close()
            return True
        except Exception as e:
            _LOGGER.exception(f"Can't run MQTT: {e}")
            return False

    def on_connect(self, client, userdata, flags, rc):
        _LOGGER.debug(f"{self.host} | MQTT connected")
        # self.mqtt.subscribe('#')
        self.mqtt.subscribe('zigbee/send')

    def on_disconnect(self, client, userdata, rc):
        _LOGGER.debug(f"{self.host} | MQTT disconnected")
        # force end mqtt.loop_forever()
        self.mqtt.disconnect()

    def on_message(self, client: Client, userdata, msg: MQTTMessage):
        if self.log:
            self.log.debug(f"[{self.host}] {msg.topic} {msg.payload.decode()}")

        if msg.topic == 'zigbee/send':
            payload = json.loads(msg.payload)
            self.process_message(payload)

    def setup_devices(self, devices: list):
        """Add devices to hass."""
        for device in devices:
            desc = utils.get_device(device['model'])
            if not desc:
                _LOGGER.debug(f"Unsupported model: {device}")
                continue

            _LOGGER.debug(f"Setup device {device['model']}")

            device.update(desc)

            if self.devices is None:
                self.devices = {}
            self.devices[device['did']] = device

            for param in device['params']:
                domain = param[3]
                if not domain:
                    continue

                # wait domain init
                while domain not in self.setups:
                    time.sleep(1)

                attr = param[2]
                self.setups[domain](self, device, attr)

    def process_message(self, data: dict):
        if data['cmd'] == 'heartbeat':
            # don't know if only one item
            assert len(data['params']) == 1, data

            data = data['params'][0]
            pkey = 'res_list'
        elif data['cmd'] == 'report':
            pkey = 'params'
        elif data['cmd'] == 'write_rsp':
            pkey = 'results'
        else:
            raise NotImplemented(f"Unsupported cmd: {data}")

        did = data['did']
        # skip without callback
        if did not in self.updates:
            return

        device = self.devices[did]
        payload = {}
        # convert codes to names
        for param in data[pkey]:
            if param.get('error_code', 0) != 0:
                continue
            prop = param['res_name']
            if prop in GLOBAL_PROP:
                prop = GLOBAL_PROP[prop]
            else:
                prop = next((p[2] for p in device['params'] if p[0] == prop),
                            prop)
            payload[prop] = (param['value'] /
                             100.0 if prop in DIV_100 else param['value'])

        _LOGGER.debug(f"{self.host} | {device['did']} {device['model']} <= "
                      f"{payload}")

        for handler in self.updates[did]:
            handler(payload)

        if 'added_device' in payload:
            device = payload['added_device']
            device['mac'] = '0x' + device['mac']
            self.setup_devices([device])

    def send(self, device: dict, param: str, value):
        # convert hass prop to lumi prop
        prop = next(p[0] for p in device['params'] if p[2] == param)
        payload = {
            'cmd': 'write',
            'did': device['did'],
            'params': [{
                'res_name': prop,
                'value': value
            }],
        }

        _LOGGER.debug(f"{self.host} | {device['did']} {device['model']} => "
                      f"{payload}")

        payload = json.dumps(payload, separators=(',', ':')).encode()
        self.mqtt.publish('zigbee/recv', payload)
예제 #22
0
class XjxToilet(BinarySensorEntity):
    def __init__(self, name, host, token):
        self._name = name
        self._device = Device(host, token)
        self._state = False
        self._state_attrs = {}
        device_info = self._device.info()
        self._unique_id = "{}-{}".format(device_info.model,
                                         device_info.mac_address)

    async def async_update(self):
        try:
            seating = self._device.get_properties(properties=['seating'])
            seatTemp = self._device.get_properties(
                properties=['seat_temp', 'status_seatheat'])
            statusLed = self._device.get_properties(properties=['status_led'])
            self._state = seating[0] == 1
            self._state_attrs.update({
                "status_seatheat": seatTemp[1] == 1,
                "seat_temp": seatTemp[0],
                "status_led": statusLed[0] == 1
            })
        except Exception:
            _LOGGER.error('Update state error.', exc_info=True)

    @property
    def name(self):
        """Return the name of the device if any."""
        return self._name

    @property
    def unique_id(self):
        """Return an unique ID."""
        return self._unique_id

    @property
    def is_on(self) -> bool:
        """Return True if the switch is on based on the state machine."""
        if self._state is None:
            return False
        return self._state

    @property
    def device_class(self):
        """Return the device class of this entity."""
        return DEVICE_CLASS_OCCUPANCY

    @property
    def device_state_attributes(self):
        """Return the state attributes of the device."""
        return self._state_attrs

    async def flush_on(self, **kwargs):
        try:
            self._device.send('flush_on', [])
        except DeviceException:
            raise PlatformNotReady

    async def work_seatheat(self, **kwargs):
        try:
            self._device.send('work_seatheat', [kwargs["status"]])
            # 开启马桶圈加热必须同时发送马桶圈温度命令
            if kwargs["status"] == 1:
                self._device.send('send_seat_heat', [kwargs["status"]])
        except DeviceException:
            raise PlatformNotReady

    async def work_night_led(self, **kwargs):
        try:
            self._device.send('work_night_led', [kwargs["status"]])
        except DeviceException:
            raise PlatformNotReady
    def update(event_time):
        """Get the latest data and updates the states."""
        try:
            miio_device = Device(host, token)

            run_status = miio_device.send('get_prop', ["run_status"])[0]
            work_status = miio_device.send('get_prop', ["work_status"])[0]
            warm_data = miio_device.send('get_prop', ["warm_data"])[0]
            last_time = miio_device.send('get_prop', ["last_time"])[0]
            last_temp = miio_device.send('get_prop', ["last_temp"])[0]
            curr_tempe = miio_device.send('get_prop', ["curr_tempe"])[0]
            # work_temps    =  miio_device.send('get_prop', ["work_temps"])[0]
            mode = miio_device.send('get_prop', ["mode"])[0]  #模式
            heat_power = miio_device.send('get_prop', ["heat_power"])[0]  #功率
            warm_time = miio_device.send('get_prop', ["warm_time"])[0]  #保温时间
            cook_time = miio_device.send('get_prop', ["cook_time"])[0]  #蒸煮时间
            left_time = miio_device.send('get_prop', ["left_time"])[0]  #剩余时间
            cook_status = miio_device.send('get_prop',
                                           ["cook_status"])[0]  #蒸煮状态
            cooked_time = miio_device.send('get_prop', ["cooked_time"])[0]
            voice = miio_device.send('get_prop', ["voice"])[0]
            stand_top_num = miio_device.send('get_prop', ["stand_top_num"])[0]
            mode_sort = miio_device.send('get_prop', ["mode_sort"])[0]

            __run_status = int(run_status)
            __work_status = int(work_status)
            __last_time = int(last_time)
            __last_temp = int(last_temp)
            __curr_tempe = int(curr_tempe)
            __work_status_cn = None
            __mode_cn = None
            __mode_en = None
            __mode = int(mode)
            __heat_power = int(heat_power)
            __warm_time = int(warm_time)
            __cook_time = int(cook_time)
            __left_time = int(left_time)
            __cook_status = int(cook_status)
            __cooked_time = int(cooked_time)
            __voice = int(voice)
            __stand_top_num = int(stand_top_num)
            __mode_sort = str(mode_sort)
            __warm_data = str(warm_data)
            # __work_temps = int(work_temps)

            if work_status == 1:
                # 预约
                __current_operation = STATE_1
                __work_status_cn = "预约"
            elif work_status == 2:
                # 烹饪
                __current_operation = STATE_2
                __work_status_cn = "烹饪"
            elif work_status == 3:
                # 暂停
                __current_operation = STATE_3
                __work_status_cn = "暂停"
            elif work_status == 4:
                # 保温
                __current_operation = STATE_4
                __work_status_cn = "保温"
            elif work_status == 5:
                # 终止
                __current_operation = STATE_4
                __work_status_cn = "终止"

            if mode == 11:
                # 花草茶
                __mode_en = MODE_11
                __mode_cn = "花草茶"
            elif mode == 12:
                # 水果茶
                __mode_en = MODE_12
                __mode_cn = "水果茶"
            elif mode == 13:
                # 煲汤
                __mode_en = MODE_13
                __mode_cn = "煲汤"
            elif mode == 14:
                # 药膳
                __mode_en = MODE_14
                __mode_cn = "药膳"
            elif mode == 15:
                # 粥品
                __mode_en = MODE_15
                __mode_cn = "粥品"
            elif mode == 16:
                # 燕窝
                __mode_en = MODE_16
                __mode_cn = "燕窝"
            elif mode == 17:
                # 火锅
                __mode_en = MODE_17
                __mode_cn = "火锅"
            elif mode == 18:
                # 烧水
                __mode_en = MODE_18
                __mode_cn = "烧水"
            elif mode == 19:
                # 温奶
                __mode_en = MODE_19
                __mode_cn = "温奶"
            elif mode == 20:
                # 温泉蛋
                __mode_en = MODE_20
                __mode_cn = "温泉蛋"
            elif mode == 21:
                # 酸奶
                __mode_en = MODE_21
                __mode_cn = "酸奶"
            elif mode == 22:
                # 蒸水蛋
                __mode_en = MODE_22
                __mode_cn = "蒸水蛋"
            elif mode == 23:
                # 煮茶
                __mode_en = MODE_23
                __mode_cn = "煮茶"
            elif mode == 24:
                # 灵芝
                __mode_en = MODE_24
                __mode_cn = "灵芝"
            elif mode == 25:
                # 消毒
                __mode_en = MODE_25
                __mode_cn = "消毒"
            elif mode == 26:
                # 糖水
                __mode_en = MODE_26
                __mode_cn = "糖水"
            elif mode == 1:
                # 自定义
                __mode_en = MODE_1
                __mode_cn = "自定义1"
            elif mode == 2:
                # 自定义
                __mode_en = MODE_2
                __mode_cn = "自定义2"
            elif mode == 3:
                # 自定义
                __mode_en = MODE_3
                __mode_cn = "自定义3"
            elif mode == 4:
                # 自定义
                __mode_en = MODE_4
                __mode_cn = "自定义4"
            elif mode == 5:
                # 自定义
                __mode_en = MODE_5
                __mode_cn = "自定义5"
            elif mode == 6:
                # 自定义
                __mode_en = MODE_6
                __mode_cn = "自定义6"
            elif mode == 7:
                # 自定义
                __mode_en = MODE_7
                __mode_cn = "自定义7"
            elif mode == 8:
                # 自定义
                __mode_en = MODE_8
                __mode_cn = "自定义8"

            __state_attrs = {
                "run_status": run_status,
                "work_status": work_status,
                "work_status_cn": __work_status_cn,
                "warm_data": warm_data,
                "last_time": last_time,
                "last_temp": last_temp,
                "curr_tempe": curr_tempe,
                # "work_temps":work_temps,
                "mode": mode,
                "mode_en": __mode_en,
                "mode_cn": __mode_cn,
                "heat_power": heat_power,
                "warm_time": warm_time,
                "cook_time": cook_time,
                "left_time": left_time,
                "cook_status": cook_status,
                "cooked_time": cooked_time,
                "voice": voice,
                "stand_top_num": stand_top_num,
                "mode_sort": mode_sort,
                "friendly_name": name
            }

            unique_id = "{}_{}".format(
                "xiaomi",
                miio_device.info().mac_address.replace(':', ''))
            entityid = "{}.{}".format(DOMAIN, unique_id)
            hass.states.set(entityid, work_status, __state_attrs)

        except DeviceException:
            _LOGGER.exception('Fail to get_prop from XiaomiHealthPot')
            raise PlatformNotReady
예제 #24
0
async def async_setup_platform(hass,
                               config,
                               async_add_entities,
                               discovery_info=None):
    """Set up the switch from config."""
    from miio import Device, DeviceException
    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)
    model = config.get(CONF_MODEL)

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    devices = []
    unique_id = None

    if model is None:
        try:
            miio_device = Device(host, token)
            device_info = miio_device.info()
            model = device_info.model
            unique_id = "{}-{}".format(model, device_info.mac_address)
            _LOGGER.info("%s %s %s detected", model,
                         device_info.firmware_version,
                         device_info.hardware_version)
        except DeviceException:
            raise PlatformNotReady

    if model in ['chuangmi.plug.v1', 'chuangmi.plug.v3']:
        from miio import ChuangmiPlug
        plug = ChuangmiPlug(host, token, model=model)

        # The device has two switchable channels (mains and a USB port).
        # A switch device per channel will be created.
        for channel_usb in [True, False]:
            device = ChuangMiPlugSwitch(name, plug, model, unique_id,
                                        channel_usb)
            devices.append(device)
            hass.data[DATA_KEY][host] = device

    elif model in ['qmi.powerstrip.v1', 'zimi.powerstrip.v2']:
        from miio import PowerStrip
        plug = PowerStrip(host, token, model=model)
        device = XiaomiPowerStripSwitch(name, plug, model, unique_id)
        devices.append(device)
        hass.data[DATA_KEY][host] = device
    elif model in ['chuangmi.plug.m1', 'chuangmi.plug.v2']:
        from miio import ChuangmiPlug
        plug = ChuangmiPlug(host, token, model=model)
        device = XiaomiPlugGenericSwitch(name, plug, model, unique_id)
        devices.append(device)
        hass.data[DATA_KEY][host] = device
    else:
        _LOGGER.error(
            'Unsupported device found! Please create an issue at '
            'https://github.com/rytilahti/python-miio/issues '
            'and provide the following data: %s', model)
        return False

    async_add_entities(devices, update_before_add=True)

    async def async_service_handler(service):
        """Map services to methods on XiaomiPlugGenericSwitch."""
        method = SERVICE_TO_METHOD.get(service.service)
        params = {
            key: value
            for key, value in service.data.items() if key != ATTR_ENTITY_ID
        }
        entity_ids = service.data.get(ATTR_ENTITY_ID)
        if entity_ids:
            devices = [
                device for device in hass.data[DATA_KEY].values()
                if device.entity_id in entity_ids
            ]
        else:
            devices = hass.data[DATA_KEY].values()

        update_tasks = []
        for device in devices:
            if not hasattr(device, method['method']):
                continue
            await getattr(device, method['method'])(**params)
            update_tasks.append(device.async_update_ha_state(True))

        if update_tasks:
            await asyncio.wait(update_tasks, loop=hass.loop)

    for plug_service in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[plug_service].get('schema', SERVICE_SCHEMA)
        hass.services.async_register(DOMAIN,
                                     plug_service,
                                     async_service_handler,
                                     schema=schema)
예제 #25
0
async def async_setup_platform(hass, config, async_add_devices,
                               discovery_info=None):
    """Set up the miio fan device from config."""
    from miio import Device, DeviceException
    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)
    model = config.get(CONF_MODEL)

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])
    unique_id = None

    if model is None:
        try:
            miio_device = Device(host, token)
            device_info = miio_device.info()
            model = device_info.model
            unique_id = "{}-{}".format(model, device_info.mac_address)
            _LOGGER.info("%s %s %s detected",
                         model,
                         device_info.firmware_version,
                         device_info.hardware_version)
        except DeviceException:
            raise PlatformNotReady

    if model.startswith('zhimi.airpurifier.'):
        from miio import AirPurifier
        air_purifier = AirPurifier(host, token)
        device = XiaomiAirPurifier(name, air_purifier, model, unique_id)
    elif model.startswith('zhimi.humidifier.'):
        from miio import AirHumidifier
        air_humidifier = AirHumidifier(host, token)
        device = XiaomiAirHumidifier(name, air_humidifier, model, unique_id)
    else:
        _LOGGER.error(
            'Unsupported device found! Please create an issue at '
            'https://github.com/syssi/xiaomi_airpurifier/issues '
            'and provide the following data: %s', model)
        return False

    hass.data[DATA_KEY][host] = device
    async_add_devices([device], update_before_add=True)

    async def async_service_handler(service):
        """Map services to methods on XiaomiAirPurifier."""
        method = SERVICE_TO_METHOD.get(service.service)
        params = {key: value for key, value in service.data.items()
                  if key != ATTR_ENTITY_ID}
        entity_ids = service.data.get(ATTR_ENTITY_ID)
        if entity_ids:
            devices = [device for device in hass.data[DATA_KEY].values() if
                       device.entity_id in entity_ids]
        else:
            devices = hass.data[DATA_KEY].values()

        update_tasks = []
        for device in devices:
            if not hasattr(device, method['method']):
                continue
            await getattr(device, method['method'])(**params)
            update_tasks.append(device.async_update_ha_state(True))

        if update_tasks:
            await asyncio.wait(update_tasks, loop=hass.loop)

    for air_purifier_service in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[air_purifier_service].get(
            'schema', AIRPURIFIER_SERVICE_SCHEMA)
        hass.services.async_register(
            DOMAIN, air_purifier_service, async_service_handler, schema=schema)
예제 #26
0
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
    """Set up the light from config."""
    from miio import Device, DeviceException
    if PLATFORM not in hass.data:
        hass.data[PLATFORM] = {}

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    try:
        light = Device(host, token)
        device_info = light.info()
        _LOGGER.info("%s %s %s initialized",
                     device_info.model,
                     device_info.firmware_version,
                     device_info.hardware_version)

        if device_info.model == 'philips.light.sread1':
            from miio import PhilipsEyecare
            light = PhilipsEyecare(host, token)
            device = XiaomiPhilipsEyecareLamp(name, light, device_info)
        elif device_info.model == 'philips.light.ceiling':
            from miio import Ceil
            light = Ceil(host, token)
            device = XiaomiPhilipsCeilingLamp(name, light, device_info)
        elif device_info.model == 'philips.light.bulb':
            from miio import PhilipsBulb
            light = PhilipsBulb(host, token)
            device = XiaomiPhilipsLightBall(name, light, device_info)
        else:
            _LOGGER.error(
                'Unsupported device found! Please create an issue at '
                'https://github.com/rytilahti/python-miio/issues '
                'and provide the following data: %s', device_info.model)
            return False

    except DeviceException:
        raise PlatformNotReady

    hass.data[PLATFORM][host] = device
    async_add_devices([device], update_before_add=True)

    @asyncio.coroutine
    def async_service_handler(service):
        """Map services to methods on Xiaomi Philips Lights."""
        method = SERVICE_TO_METHOD.get(service.service)
        params = {key: value for key, value in service.data.items()
                  if key != ATTR_ENTITY_ID}
        entity_ids = service.data.get(ATTR_ENTITY_ID)
        if entity_ids:
            target_devices = [dev for dev in hass.data[PLATFORM].values()
                              if dev.entity_id in entity_ids]
        else:
            target_devices = hass.data[PLATFORM].values()

        update_tasks = []
        for target_device in target_devices:
            yield from getattr(target_device, method['method'])(**params)
            update_tasks.append(target_device.async_update_ha_state(True))

        if update_tasks:
            yield from asyncio.wait(update_tasks, loop=hass.loop)

    for xiaomi_miio_service in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[xiaomi_miio_service].get(
            'schema', XIAOMI_MIIO_SERVICE_SCHEMA)
        hass.services.async_register(
            DOMAIN, xiaomi_miio_service, async_service_handler, schema=schema)
예제 #27
0
    async def async_step_user(self, user_input=None):
        """Handle a flow initialized by the user."""
        errors = {}

        # Check if already configured
        # await self.async_set_unique_id(DOMAIN)
        # self._abort_if_unique_id_configured()

        if user_input is not None:

            self._name = user_input[CONF_NAME]
            self._host = user_input[CONF_HOST]
            self._token = user_input[CONF_TOKEN]
            # self._mapping = user_input[CONF_MAPPING]
            # self._params = user_input[CONF_CONTROL_PARAMS]

            device = MiioDevice(self._host, self._token)
            try:
                self._info = device.info()
            except DeviceException:
                # print("DeviceException!!!!!!")
                errors['base'] = 'cannot_connect'
            # except ValueError:
            #     errors['base'] = 'value_error'

            if self._info is not None:
                unique_id = format_mac(self._info.mac_address)
                # await self.async_set_unique_id(unique_id)
                for entry in self._async_current_entries():
                    if entry.unique_id == unique_id:
                        persistent_notification.async_create(
                            self.hass, f"您新添加的设备: **{self._name}** ,\n"
                            f"其 MAC 地址与现有的某个设备相同。\n"
                            f"只是通知,不会造成任何影响。", "设备可能重复")
                        break

                self._abort_if_unique_id_configured()
                d = self._info.raw
                self._model = d['model']
                device_info = (f"Model: {d['model']}\n"
                               f"Firmware: {d['fw_ver']}\n"
                               f"MAC: {d['mac']}\n")

                # self._info = self.get_devconfg_by_model(self._model)

                self._info = await async_get_mp_from_net(self.hass, self._model) \
                    or await guess_mp_from_model(self.hass, self._model)

                if self._info:
                    device_info += "\n已经自动发现配置参数。\n如无特殊需要,无需修改下列内容。\n"
                    devtype_default = self._info.get('device_type')
                    mapping_default = self._info.get('mapping')
                    params_default = self._info.get('params')
                else:
                    device_info += "请手动进行配置。\n"
                    devtype_default = ''
                    mapping_default = '{"switch_status":{"siid":2,"piid":1}}'
                    params_default = '{"switch_status":{"power_on":true,"power_off":false}}'

                self._input2 = user_input
                return self.async_show_form(
                    step_id="devinfo",
                    data_schema=vol.Schema({
                        vol.Required('devtype', default=devtype_default):
                        vol.In(SUPPORTED_DOMAINS),
                        vol.Required(CONF_MAPPING, default=mapping_default):
                        str,
                        vol.Required(CONF_CONTROL_PARAMS,
                                     default=params_default):
                        str,
                        vol.Optional('cloud_read'):
                        bool,
                        vol.Optional('cloud_write'):
                        bool,
                    }),
                    description_placeholders={"device_info": device_info},
                    errors=errors,
                )

        return self.async_show_form(
            step_id="user",
            data_schema=vol.Schema({
                vol.Required(CONF_NAME):
                str,
                vol.Required(CONF_HOST, default='192.168.'):
                str,
                vol.Required(CONF_TOKEN):
                str,
                # vol.Required(CONF_MAPPING, default='{"switch_status":{"siid":2,"piid":1}}'): str,
                # vol.Required(CONF_CONTROL_PARAMS, default='{"switch_status":{"power_on":true,"power_off":false}}'): str,
            }),
            # description_placeholders={"device_info": "device_info"},
            errors=errors,
        )
예제 #28
0
async def async_setup_platform(hass, config, async_add_entities,
                               discovery_info=None):
    """Set up the miio fan device from config."""
    from miio import Device, DeviceException
    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)
    model = config.get(CONF_MODEL)

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])
    unique_id = None

    if model is None:
        try:
            miio_device = Device(host, token)
            device_info = miio_device.info()
            model = device_info.model
            unique_id = "{}-{}".format(model, device_info.mac_address)
            _LOGGER.info("%s %s %s detected",
                         model,
                         device_info.firmware_version,
                         device_info.hardware_version)
        except DeviceException:
            raise PlatformNotReady

    if model.startswith('zhimi.airpurifier.'):
        from miio import AirPurifier
        air_purifier = AirPurifier(host, token)
        device = XiaomiAirPurifier(name, air_purifier, model, unique_id)
    elif model.startswith('zhimi.humidifier.'):
        from miio import AirHumidifier
        air_humidifier = AirHumidifier(host, token, model=model)
        device = XiaomiAirHumidifier(name, air_humidifier, model, unique_id)
    elif model.startswith('zhimi.airfresh.'):
        from miio import AirFresh
        air_fresh = AirFresh(host, token)
        device = XiaomiAirFresh(name, air_fresh, model, unique_id)
    else:
        _LOGGER.error(
            'Unsupported device found! Please create an issue at '
            'https://github.com/syssi/xiaomi_airpurifier/issues '
            'and provide the following data: %s', model)
        return False

    hass.data[DATA_KEY][host] = device
    async_add_entities([device], update_before_add=True)

    async def async_service_handler(service):
        """Map services to methods on XiaomiAirPurifier."""
        method = SERVICE_TO_METHOD.get(service.service)
        params = {key: value for key, value in service.data.items()
                  if key != ATTR_ENTITY_ID}
        entity_ids = service.data.get(ATTR_ENTITY_ID)
        if entity_ids:
            devices = [device for device in hass.data[DATA_KEY].values() if
                       device.entity_id in entity_ids]
        else:
            devices = hass.data[DATA_KEY].values()

        update_tasks = []
        for device in devices:
            if not hasattr(device, method['method']):
                continue
            await getattr(device, method['method'])(**params)
            update_tasks.append(device.async_update_ha_state(True))

        if update_tasks:
            await asyncio.wait(update_tasks, loop=hass.loop)

    for air_purifier_service in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[air_purifier_service].get(
            'schema', AIRPURIFIER_SERVICE_SCHEMA)
        hass.services.async_register(
            DOMAIN, air_purifier_service, async_service_handler, schema=schema)
def setup(hass, config):
    from miio import Device, DeviceException
    if DOMAIN not in hass.data:
        hass.data[DOMAIN] = {}
    host = config[DOMAIN][CONF_HOST]
    token = config[DOMAIN][CONF_TOKEN]
    name = config[DOMAIN][CONF_NAME]
    model = config[DOMAIN].get(CONF_MODEL)
    scan_interval = config[DOMAIN][CONF_SCAN_INTERVAL]

    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}
        hass.data[DATA_KEY][host] = {}

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    devices = []
    if model is None:
        try:
            miio_device = Device(host, token)
            device_info = miio_device.info()
            model = device_info.model
            _LOGGER.info(
                "%s %s %s detected",
                model,
                device_info.firmware_version,
                device_info.hardware_version,
            )
        except DeviceException:
            raise PlatformNotReady

    if model not in SUPPORTED_MODELS:

        _LOGGER.error(
            "Unsupported device found! Please create an issue at "
            "https://github.com/fineemb/Xiaomi-Smart-Multipurpose-Kettle/issues "
            "and provide the following data: %s",
            model,
        )
        return False

    def update(event_time):
        """Get the latest data and updates the states."""
        try:
            miio_device = Device(host, token)

            run_status = miio_device.send('get_prop', ["run_status"])[0]
            work_status = miio_device.send('get_prop', ["work_status"])[0]
            warm_data = miio_device.send('get_prop', ["warm_data"])[0]
            last_time = miio_device.send('get_prop', ["last_time"])[0]
            last_temp = miio_device.send('get_prop', ["last_temp"])[0]
            curr_tempe = miio_device.send('get_prop', ["curr_tempe"])[0]
            # work_temps    =  miio_device.send('get_prop', ["work_temps"])[0]
            mode = miio_device.send('get_prop', ["mode"])[0]  #模式
            heat_power = miio_device.send('get_prop', ["heat_power"])[0]  #功率
            warm_time = miio_device.send('get_prop', ["warm_time"])[0]  #保温时间
            cook_time = miio_device.send('get_prop', ["cook_time"])[0]  #蒸煮时间
            left_time = miio_device.send('get_prop', ["left_time"])[0]  #剩余时间
            cook_status = miio_device.send('get_prop',
                                           ["cook_status"])[0]  #蒸煮状态
            cooked_time = miio_device.send('get_prop', ["cooked_time"])[0]
            voice = miio_device.send('get_prop', ["voice"])[0]
            stand_top_num = miio_device.send('get_prop', ["stand_top_num"])[0]
            mode_sort = miio_device.send('get_prop', ["mode_sort"])[0]

            __run_status = int(run_status)
            __work_status = int(work_status)
            __last_time = int(last_time)
            __last_temp = int(last_temp)
            __curr_tempe = int(curr_tempe)
            __work_status_cn = None
            __mode_cn = None
            __mode_en = None
            __mode = int(mode)
            __heat_power = int(heat_power)
            __warm_time = int(warm_time)
            __cook_time = int(cook_time)
            __left_time = int(left_time)
            __cook_status = int(cook_status)
            __cooked_time = int(cooked_time)
            __voice = int(voice)
            __stand_top_num = int(stand_top_num)
            __mode_sort = str(mode_sort)
            __warm_data = str(warm_data)
            # __work_temps = int(work_temps)

            if work_status == 1:
                # 预约
                __current_operation = STATE_1
                __work_status_cn = "预约"
            elif work_status == 2:
                # 烹饪
                __current_operation = STATE_2
                __work_status_cn = "烹饪"
            elif work_status == 3:
                # 暂停
                __current_operation = STATE_3
                __work_status_cn = "暂停"
            elif work_status == 4:
                # 保温
                __current_operation = STATE_4
                __work_status_cn = "保温"
            elif work_status == 5:
                # 终止
                __current_operation = STATE_4
                __work_status_cn = "终止"

            if mode == 11:
                # 花草茶
                __mode_en = MODE_11
                __mode_cn = "花草茶"
            elif mode == 12:
                # 水果茶
                __mode_en = MODE_12
                __mode_cn = "水果茶"
            elif mode == 13:
                # 煲汤
                __mode_en = MODE_13
                __mode_cn = "煲汤"
            elif mode == 14:
                # 药膳
                __mode_en = MODE_14
                __mode_cn = "药膳"
            elif mode == 15:
                # 粥品
                __mode_en = MODE_15
                __mode_cn = "粥品"
            elif mode == 16:
                # 燕窝
                __mode_en = MODE_16
                __mode_cn = "燕窝"
            elif mode == 17:
                # 火锅
                __mode_en = MODE_17
                __mode_cn = "火锅"
            elif mode == 18:
                # 烧水
                __mode_en = MODE_18
                __mode_cn = "烧水"
            elif mode == 19:
                # 温奶
                __mode_en = MODE_19
                __mode_cn = "温奶"
            elif mode == 20:
                # 温泉蛋
                __mode_en = MODE_20
                __mode_cn = "温泉蛋"
            elif mode == 21:
                # 酸奶
                __mode_en = MODE_21
                __mode_cn = "酸奶"
            elif mode == 22:
                # 蒸水蛋
                __mode_en = MODE_22
                __mode_cn = "蒸水蛋"
            elif mode == 23:
                # 煮茶
                __mode_en = MODE_23
                __mode_cn = "煮茶"
            elif mode == 24:
                # 灵芝
                __mode_en = MODE_24
                __mode_cn = "灵芝"
            elif mode == 25:
                # 消毒
                __mode_en = MODE_25
                __mode_cn = "消毒"
            elif mode == 26:
                # 糖水
                __mode_en = MODE_26
                __mode_cn = "糖水"
            elif mode == 1:
                # 自定义
                __mode_en = MODE_1
                __mode_cn = "自定义1"
            elif mode == 2:
                # 自定义
                __mode_en = MODE_2
                __mode_cn = "自定义2"
            elif mode == 3:
                # 自定义
                __mode_en = MODE_3
                __mode_cn = "自定义3"
            elif mode == 4:
                # 自定义
                __mode_en = MODE_4
                __mode_cn = "自定义4"
            elif mode == 5:
                # 自定义
                __mode_en = MODE_5
                __mode_cn = "自定义5"
            elif mode == 6:
                # 自定义
                __mode_en = MODE_6
                __mode_cn = "自定义6"
            elif mode == 7:
                # 自定义
                __mode_en = MODE_7
                __mode_cn = "自定义7"
            elif mode == 8:
                # 自定义
                __mode_en = MODE_8
                __mode_cn = "自定义8"

            __state_attrs = {
                "run_status": run_status,
                "work_status": work_status,
                "work_status_cn": __work_status_cn,
                "warm_data": warm_data,
                "last_time": last_time,
                "last_temp": last_temp,
                "curr_tempe": curr_tempe,
                # "work_temps":work_temps,
                "mode": mode,
                "mode_en": __mode_en,
                "mode_cn": __mode_cn,
                "heat_power": heat_power,
                "warm_time": warm_time,
                "cook_time": cook_time,
                "left_time": left_time,
                "cook_status": cook_status,
                "cooked_time": cooked_time,
                "voice": voice,
                "stand_top_num": stand_top_num,
                "mode_sort": mode_sort,
                "friendly_name": name
            }

            unique_id = "{}_{}".format(
                "xiaomi",
                miio_device.info().mac_address.replace(':', ''))
            entityid = "{}.{}".format(DOMAIN, unique_id)
            hass.states.set(entityid, work_status, __state_attrs)

        except DeviceException:
            _LOGGER.exception('Fail to get_prop from XiaomiHealthPot')
            raise PlatformNotReady

    track_time_interval(hass, update, scan_interval)

    def set_voice(voice: str):
        try:
            miio_device = Device(host, token)
            if voice == 'on':
                miio_device.send('set_voice', [0])
            elif voice == 'off':
                miio_device.send('set_voice', [1])
        except DeviceException:
            raise PlatformNotReady

    def set_work(**kwargs):
        """Set work."""
        try:
            miio_device = Device(host, token)
            miio_device.send('set_work', [
                kwargs["status"], kwargs["id"], kwargs["keep_temp"],
                kwargs["keep_time"], kwargs["timestamp"]
            ])
        except DeviceException:
            raise PlatformNotReady

    def delete_modes(**kwargs):
        """Delete work.删除自定义模式"""
        try:
            miio_device = Device(host, token)
            miio_device.send('delete_modes', [kwargs["modes"]])
        except DeviceException:
            raise PlatformNotReady

    def set_mode_sort(**kwargs):
        """Set mode sort.设置模式排序"""
        try:
            miio_device = Device(host, token)
            miio_device.send('set_mode_sort', [kwargs["sort"]])
        except DeviceException:
            raise PlatformNotReady

    def set_mode(**kwargs):
        """Set mode.设置自定义模式"""
        try:
            miio_device = Device(host, token)
            miio_device.send('set_mode',
                             [kwargs["id"], kwargs["heat"], kwargs["time"]])
        except DeviceException:
            raise PlatformNotReady

    def service_handle(service):
        params = {key: value for key, value in service.data.items()}

        if service.service == SERVICE_SET_VOICE:
            set_voice(**params)

        if service.service == SERVICE_SET_WORK:
            set_work(**params)

        if service.service == SERVICE_DELETE_MODES:
            delete_modes(**params)

        if service.service == SERVICE_SET_MODE_SORT:
            set_mode_sort(**params)

        if service.service == SERVICE_SET_MODE:
            set_mode(**params)

    hass.services.register(DOMAIN,
                           SERVICE_SET_VOICE,
                           service_handle,
                           schema=SERVICE_SCHEMA_SET_VOICE)
    hass.services.register(DOMAIN,
                           SERVICE_SET_WORK,
                           service_handle,
                           schema=SERVICE_SCHEMA_SET_WORK)
    hass.services.register(DOMAIN,
                           SERVICE_DELETE_MODES,
                           service_handle,
                           schema=SERVICE_SCHEMA_DEL_MODES)
    hass.services.register(DOMAIN,
                           SERVICE_SET_MODE_SORT,
                           service_handle,
                           schema=SERVICE_SCHEMA_SET_MODE_SORT)
    hass.services.register(DOMAIN,
                           SERVICE_SET_MODE,
                           service_handle,
                           schema=SERVICE_SCHEMA_SET_MODE)

    return True
예제 #30
0
async def async_setup_platform(hass, config, async_add_entities,
                               discovery_info=None):
    """Set up the light from config."""
    from miio import Device, DeviceException
    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)
    model = config.get(CONF_MODEL)

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    devices = []
    unique_id = None

    if model is None:
        try:
            miio_device = Device(host, token)
            device_info = miio_device.info()
            model = device_info.model
            unique_id = "{}-{}".format(model, device_info.mac_address)
            _LOGGER.info("%s %s %s detected",
                         model,
                         device_info.firmware_version,
                         device_info.hardware_version)
        except DeviceException:
            raise PlatformNotReady

    if model == 'philips.light.sread1':
        from miio import PhilipsEyecare
        light = PhilipsEyecare(host, token)
        primary_device = XiaomiPhilipsEyecareLamp(
            name, light, model, unique_id)
        devices.append(primary_device)
        hass.data[DATA_KEY][host] = primary_device

        secondary_device = XiaomiPhilipsEyecareLampAmbientLight(
            name, light, model, unique_id)
        devices.append(secondary_device)
        # The ambient light doesn't expose additional services.
        # A hass.data[DATA_KEY] entry isn't needed.
    elif model in ['philips.light.ceiling', 'philips.light.zyceiling']:
        from miio import Ceil
        light = Ceil(host, token)
        device = XiaomiPhilipsCeilingLamp(name, light, model, unique_id)
        devices.append(device)
        hass.data[DATA_KEY][host] = device
    elif model == 'philips.light.moonlight':
        from miio import PhilipsMoonlight
        light = PhilipsMoonlight(host, token)
        device = XiaomiPhilipsMoonlightLamp(name, light, model, unique_id)
        devices.append(device)
        hass.data[DATA_KEY][host] = device
    elif model in ['philips.light.bulb',
                   'philips.light.candle',
                   'philips.light.candle2',
                   'philips.light.downlight']:
        from miio import PhilipsBulb
        light = PhilipsBulb(host, token)
        device = XiaomiPhilipsBulb(name, light, model, unique_id)
        devices.append(device)
        hass.data[DATA_KEY][host] = device
    elif model == 'philips.light.mono1':
        from miio import PhilipsBulb
        light = PhilipsBulb(host, token)
        device = XiaomiPhilipsGenericLight(name, light, model, unique_id)
        devices.append(device)
        hass.data[DATA_KEY][host] = device
    else:
        _LOGGER.error(
            'Unsupported device found! Please create an issue at '
            'https://github.com/syssi/philipslight/issues '
            'and provide the following data: %s', model)
        return False

    async_add_entities(devices, update_before_add=True)

    async def async_service_handler(service):
        """Map services to methods on Xiaomi Philips Lights."""
        method = SERVICE_TO_METHOD.get(service.service)
        params = {key: value for key, value in service.data.items()
                  if key != ATTR_ENTITY_ID}
        entity_ids = service.data.get(ATTR_ENTITY_ID)
        if entity_ids:
            target_devices = [dev for dev in hass.data[DATA_KEY].values()
                              if dev.entity_id in entity_ids]
        else:
            target_devices = hass.data[DATA_KEY].values()

        update_tasks = []
        for target_device in target_devices:
            if not hasattr(target_device, method['method']):
                continue
            await getattr(target_device, method['method'])(**params)
            update_tasks.append(target_device.async_update_ha_state(True))

        if update_tasks:
            await asyncio.wait(update_tasks, loop=hass.loop)

    for xiaomi_miio_service in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[xiaomi_miio_service].get(
            'schema', XIAOMI_MIIO_SERVICE_SCHEMA)
        hass.services.async_register(
            DOMAIN, xiaomi_miio_service, async_service_handler, schema=schema)
예제 #31
0
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
    """Set up the miio fan device from config."""
    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}

    host = config[CONF_HOST]
    name = config[CONF_NAME]
    token = config[CONF_TOKEN]
    model = config.get(CONF_MODEL)

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])
    unique_id = None

    if model is None:
        miio_device = Device(host, token)
        try:
            device_info = miio_device.info()
        except DeviceException:
            raise PlatformNotReady

        model = device_info.model
        unique_id = "{}-{}".format(model, device_info.mac_address)
        _LOGGER.info(
            "%s %s %s detected",
            model,
            device_info.firmware_version,
            device_info.hardware_version,
        )

    if model.startswith("nwt.derh."):
        air_dehumidifier = AirDehumidifier(host, token, model=model)
        device = XiaomiAirDehumidifier(name, air_dehumidifier, model, unique_id)
    else:
        _LOGGER.error(
            "Unsupported device found! Please create an issue at "
            "https://github.com/rytilahti/python-miio/issues "
            "and provide the following data: %s",
            model,
        )
        return False

    hass.data[DATA_KEY][host] = device
    async_add_entities([device], update_before_add=True)

    async def async_service_handler(service):
        """Map services to methods on XiaomiAirDehumidifier."""
        method = SERVICE_TO_METHOD.get(service.service)
        params = {
            key: value for key, value in service.data.items() if key != ATTR_ENTITY_ID
        }
        entity_ids = service.data.get(ATTR_ENTITY_ID)
        if entity_ids:
            devices = [
                device
                for device in hass.data[DATA_KEY].values()
                if device.entity_id in entity_ids
            ]
        else:
            devices = hass.data[DATA_KEY].values()

        update_tasks = []
        for device in devices:
            if not hasattr(device, method["method"]):
                continue
            await getattr(device, method["method"])(**params)
            update_tasks.append(device.async_update_ha_state(True))

        if update_tasks:
            await asyncio.wait(update_tasks)

    for air_dehumidifier_service in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[air_dehumidifier_service].get(
            "schema", AIRDEHUMIDIFIER_SERVICE_SCHEMA
        )
        hass.services.async_register(
            DOMAIN, air_dehumidifier_service, async_service_handler, schema=schema
        )
def setup(hass, config):
    #    from miio import Device, DeviceException
    if DOMAIN not in hass.data:
        hass.data[DOMAIN] = {}
    host = config[DOMAIN][CONF_HOST]
    token = config[DOMAIN][CONF_TOKEN]
    name = config[DOMAIN][CONF_NAME]
    model = config[DOMAIN].get(CONF_MODEL)
    scan_interval = config[DOMAIN][CONF_SCAN_INTERVAL]

    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}
        hass.data[DATA_KEY][host] = {}

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    devices = []
    if model is None:
        try:
            miio_device = Device(host, token)
            device_info = miio_device.info()
            model = device_info.model
            _LOGGER.info(
                "%s %s %s detected",
                model,
                device_info.firmware_version,
                device_info.hardware_version,
            )
        except DeviceException:
            raise PlatformNotReady

    if model not in SUPPORTED_MODELS:

        _LOGGER.error(
            "Unsupported device found! Please create an issue at "
            "https://github.com/fineemb/Xiaomi-Smart-Multipurpose-Kettle/issues "
            "and provide the following data: %s",
            model,
        )
        return False

    def update(event_time):
        """Get the latest data and updates the states."""
        try:
            miio_device = Device(host, token)

            run_status = miio_device.send('get_prop', ["run_status"])[0]
            work_status = miio_device.send('get_prop', ["work_status"])[0]
            #warm_data     =  miio_device.send('get_prop', ["warm_data"])[0]
            last_time = miio_device.send('get_prop', ["last_time"])[0]
            last_temp = miio_device.send('get_prop', ["last_temp"])[0]
            curr_tempe = miio_device.send('get_prop', ["curr_tempe"])[0]
            # work_temps    =  miio_device.send('get_prop', ["work_temps"])[0]
            mode = miio_device.send('get_prop', ["mode"])[0]  #模式
            heat_power = miio_device.send('get_prop', ["heat_power"])[0]  #功率
            warm_time = miio_device.send('get_prop', ["warm_time"])[0]  #保温时间
            cook_time = miio_device.send('get_prop', ["cook_time"])[0]  #蒸煮时间
            left_time = miio_device.send('get_prop', ["left_time"])[0]  #剩余时间
            cook_status = miio_device.send('get_prop',
                                           ["cook_status"])[0]  #蒸煮状态
            cooked_time = miio_device.send('get_prop', ["cooked_time"])[0]
            voice = miio_device.send('get_prop', ["voice"])[0]
            stand_top_num = miio_device.send('get_prop', ["stand_top_num"])[0]
            #mode_sort     =  miio_device.send('get_prop', ["mode_sort"])[0]

            __state_attrs = {
                "run_status": AVAILABLE_RUN_STATUS[int(run_status)],
                "mode": AVAILABLE_MODE[int(mode)],
                "last_time": last_time,
                "last_temp": last_temp,
                "curr_tempe": curr_tempe,
                # "work_temps":work_temps,
                "heat_power": heat_power,
                "warm_time": warm_time,
                "cook_time": cook_time,
                "left_time": left_time,
                "cook_status": cook_status,
                "cooked_time": cooked_time,
                "voice": voice,
                "stand_top_num": stand_top_num,
                #"mode_sort":mode_sort,
                #"warm_data":warm_data,
                "friendly_name": name
            }

            unique_id = "{}_{}".format(
                "xiaomi",
                miio_device.info().mac_address.replace(':', ''))
            entityid = "{}.{}".format(DOMAIN, unique_id)
            hass.states.set(entityid, AVAILABLE_STATE[int(work_status)],
                            __state_attrs)

        except DeviceException:
            _LOGGER.exception('Fail to get_prop from XiaomiHealthPot')
            raise PlatformNotReady

    track_time_interval(hass, update, scan_interval)

    def set_voice(voice: str):
        try:
            miio_device = Device(host, token)
            if voice == 'on':
                miio_device.send('set_voice', [0])
            elif voice == 'off':
                miio_device.send('set_voice', [1])
        except DeviceException:
            raise PlatformNotReady

    def set_work(**kwargs):
        """Set work."""
        try:
            miio_device = Device(host, token)
            miio_device.send('set_work', [
                kwargs["status"], kwargs["id"], kwargs["keep_temp"],
                kwargs["keep_time"], kwargs["timestamp"]
            ])
        except DeviceException:
            raise PlatformNotReady

    def delete_modes(**kwargs):
        """Delete work.删除自定义模式"""
        try:
            miio_device = Device(host, token)
            miio_device.send('delete_modes', [kwargs["modes"]])
        except DeviceException:
            raise PlatformNotReady

    def set_mode_sort(**kwargs):
        """Set mode sort.设置模式排序"""
        try:
            miio_device = Device(host, token)
            miio_device.send('set_mode_sort', [kwargs["sort"]])
        except DeviceException:
            raise PlatformNotReady

    def set_mode(**kwargs):
        """Set mode.设置自定义模式"""
        try:
            miio_device = Device(host, token)
            miio_device.send('set_mode',
                             [kwargs["id"], kwargs["heat"], kwargs["time"]])
        except DeviceException:
            raise PlatformNotReady

    def service_handle(service):
        params = {key: value for key, value in service.data.items()}

        if service.service == SERVICE_SET_VOICE:
            set_voice(**params)

        if service.service == SERVICE_SET_WORK:
            set_work(**params)

        if service.service == SERVICE_DELETE_MODES:
            delete_modes(**params)

        if service.service == SERVICE_SET_MODE_SORT:
            set_mode_sort(**params)

        if service.service == SERVICE_SET_MODE:
            set_mode(**params)

    hass.services.register(DOMAIN,
                           SERVICE_SET_VOICE,
                           service_handle,
                           schema=SERVICE_SCHEMA_SET_VOICE)
    hass.services.register(DOMAIN,
                           SERVICE_SET_WORK,
                           service_handle,
                           schema=SERVICE_SCHEMA_SET_WORK)
    hass.services.register(DOMAIN,
                           SERVICE_DELETE_MODES,
                           service_handle,
                           schema=SERVICE_SCHEMA_DEL_MODES)
    hass.services.register(DOMAIN,
                           SERVICE_SET_MODE_SORT,
                           service_handle,
                           schema=SERVICE_SCHEMA_SET_MODE_SORT)
    hass.services.register(DOMAIN,
                           SERVICE_SET_MODE,
                           service_handle,
                           schema=SERVICE_SCHEMA_SET_MODE)

    return True
예제 #33
0
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
    """Set up the light from config."""
    from miio import Device, DeviceException
    if PLATFORM not in hass.data:
        hass.data[PLATFORM] = {}

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])

    try:
        light = Device(host, token)
        device_info = light.info()
        _LOGGER.info("%s %s %s initialized", device_info.model,
                     device_info.firmware_version,
                     device_info.hardware_version)

        if device_info.model == 'philips.light.sread1':
            from miio import PhilipsEyecare
            light = PhilipsEyecare(host, token)
            device = XiaomiPhilipsEyecareLamp(name, light, device_info)
        elif device_info.model == 'philips.light.ceiling':
            from miio import Ceil
            light = Ceil(host, token)
            device = XiaomiPhilipsCeilingLamp(name, light, device_info)
        elif device_info.model == 'philips.light.bulb':
            from miio import PhilipsBulb
            light = PhilipsBulb(host, token)
            device = XiaomiPhilipsLightBall(name, light, device_info)
        else:
            _LOGGER.error(
                'Unsupported device found! Please create an issue at '
                'https://github.com/rytilahti/python-miio/issues '
                'and provide the following data: %s', device_info.model)
            return False

    except DeviceException:
        raise PlatformNotReady

    hass.data[PLATFORM][host] = device
    async_add_devices([device], update_before_add=True)

    @asyncio.coroutine
    def async_service_handler(service):
        """Map services to methods on Xiaomi Philips Lights."""
        method = SERVICE_TO_METHOD.get(service.service)
        params = {
            key: value
            for key, value in service.data.items() if key != ATTR_ENTITY_ID
        }
        entity_ids = service.data.get(ATTR_ENTITY_ID)
        if entity_ids:
            target_devices = [
                dev for dev in hass.data[PLATFORM].values()
                if dev.entity_id in entity_ids
            ]
        else:
            target_devices = hass.data[PLATFORM].values()

        update_tasks = []
        for target_device in target_devices:
            yield from getattr(target_device, method['method'])(**params)
            update_tasks.append(target_device.async_update_ha_state(True))

        if update_tasks:
            yield from asyncio.wait(update_tasks, loop=hass.loop)

    for xiaomi_miio_service in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[xiaomi_miio_service].get(
            'schema', XIAOMI_MIIO_SERVICE_SCHEMA)
        hass.services.async_register(DOMAIN,
                                     xiaomi_miio_service,
                                     async_service_handler,
                                     schema=schema)
예제 #34
0
async def async_setup_platform(hass,
                               config,
                               async_add_devices,
                               discovery_info=None):
    """Set up the miio fan device from config."""
    from miio import Device, DeviceException

    if DATA_KEY not in hass.data:
        hass.data[DATA_KEY] = {}

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    token = config.get(CONF_TOKEN)
    model = config.get(CONF_MODEL)
    retries = config.get(CONF_RETRIES)

    _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])
    unique_id = None

    if model is None:
        try:
            miio_device = Device(host, token)
            device_info = miio_device.info()
            model = device_info.model
            unique_id = "{}-{}".format(model, device_info.mac_address)
            _LOGGER.info(
                "%s %s %s detected",
                model,
                device_info.firmware_version,
                device_info.hardware_version,
            )
        except DeviceException:
            raise PlatformNotReady

    if model in [
            MODEL_FAN_V2,
            MODEL_FAN_V3,
            MODEL_FAN_SA1,
            MODEL_FAN_ZA1,
            MODEL_FAN_ZA3,
            MODEL_FAN_ZA4,
    ]:
        from miio import Fan

        fan = Fan(host, token, model=model)
        device = XiaomiFan(name, fan, model, unique_id, retries)
    elif model == MODEL_FAN_P5:
        from miio import FanP5

        fan = FanP5(host, token, model=model)
        device = XiaomiFanP5(name, fan, model, unique_id, retries)
    else:
        _LOGGER.error(
            "Unsupported device found! Please create an issue at "
            "https://github.com/syssi/xiaomi_fan/issues "
            "and provide the following data: %s",
            model,
        )
        return False

    hass.data[DATA_KEY][host] = device
    async_add_devices([device], update_before_add=True)

    async def async_service_handler(service):
        """Map services to methods on XiaomiFan."""
        method = SERVICE_TO_METHOD.get(service.service)
        params = {
            key: value
            for key, value in service.data.items() if key != ATTR_ENTITY_ID
        }
        entity_ids = service.data.get(ATTR_ENTITY_ID)
        if entity_ids:
            devices = [
                device for device in hass.data[DATA_KEY].values()
                if device.entity_id in entity_ids
            ]
        else:
            devices = hass.data[DATA_KEY].values()

        update_tasks = []
        for device in devices:
            if not hasattr(device, method["method"]):
                continue
            await getattr(device, method["method"])(**params)
            update_tasks.append(device.async_update_ha_state(True))

        if update_tasks:
            await asyncio.wait(update_tasks, loop=hass.loop)

    for air_purifier_service in SERVICE_TO_METHOD:
        schema = SERVICE_TO_METHOD[air_purifier_service].get(
            "schema", AIRPURIFIER_SERVICE_SCHEMA)
        hass.services.async_register(DOMAIN,
                                     air_purifier_service,
                                     async_service_handler,
                                     schema=schema)
예제 #35
0
    async def async_step_localinfo(self, user_input=None):  # 2. 手动接入,本地通信信息
        """Handle a flow initialized by the user."""
        errors = {}

        # Check if already configured
        # await self.async_set_unique_id(DOMAIN)
        # self._abort_if_unique_id_configured()

        if user_input is not None:

            self._name = user_input[CONF_NAME]
            self._host = user_input[CONF_HOST]
            if user_input[CONF_TOKEN] == '0':
                user_input[CONF_TOKEN] = '0' * 32
            self._token = user_input[CONF_TOKEN]
            self._input2 = {**self._input2, **user_input}

            device = MiioDevice(self._host, self._token)
            try:
                self._info = device.info()
            except DeviceException:
                errors['base'] = 'cannot_connect'
            # except ValueError:
            #     errors['base'] = 'value_error'

            if self._info is not None:
                unique_id = format_mac(self._info.mac_address)
                # await self.async_set_unique_id(unique_id)
                for entry in self._async_current_entries():
                    if entry.unique_id == unique_id:
                        persistent_notification.async_create(
                            self.hass, f"您新添加的设备: **{self._name}** ,\n"
                            f"其 MAC 地址与现有的某个设备相同。\n"
                            f"只是通知,不会造成任何影响。", "设备可能重复")
                        break

                self._abort_if_unique_id_configured()
                d = self._info.raw
                self._model = d['model']
                device_info = (f"Model: {d['model']}\n"
                               f"Firmware: {d['fw_ver']}\n"
                               f"MAC: {d['mac']}\n")

                self._info = await guess_mp_from_model(self.hass, self._model)

                if self._info and self._info.get('mapping') != "{}":
                    device_info += "\n已经自动发现配置参数。\n如无特殊需要,无需修改下列内容。\n"
                    devtype_default = self._info.get('device_type')

                    mp = self._info.get('mapping')
                    prm = self._info.get('params')
                    mapping_default = mp
                    params_default = prm
                else:
                    device_info += f"很抱歉,未能自动发现配置参数。但这不代表您的设备不受支持。\n您可以[手工编写配置](https://github.com/ha0y/xiaomi_miot_raw/#文件配置法),或者将型号 **{self._model}** 报告给作者。"
                    devtype_default = ['switch']
                    mapping_default = '{"switch":{"switch_status":{"siid":2,"piid":1}}}'
                    params_default = '{"switch":{"switch_status":{"power_on":true,"power_off":false}}}'

                if not self._non_interactive:
                    return self.async_show_form(
                        step_id="devinfo",
                        data_schema=vol.Schema(
                            {
                                vol.Required('devtype',
                                             default=devtype_default):
                                cv.multi_select(SUPPORTED_DOMAINS),
                                vol.Required(CONF_MAPPING,
                                             default=mapping_default):
                                str,
                                vol.Required(CONF_CONTROL_PARAMS,
                                             default=params_default):
                                str,
                                vol.Optional('cloud_read'):
                                bool,
                                vol.Optional('cloud_write'):
                                bool,
                            }),
                        description_placeholders={"device_info": device_info},
                        errors=errors,
                    )
                else:
                    return await self.async_step_devinfo({
                        'devtype': devtype_default,
                        CONF_MAPPING: mapping_default,
                        CONF_CONTROL_PARAMS: params_default,
                        'cloud_read': True,
                        'cloud_write': True,
                    })
            else:
                return await self.async_step_xiaoai(
                    {CONF_MODEL: self._model} if self._model else None)

        return self.async_show_form(
            step_id="localinfo",
            data_schema=vol.Schema({
                vol.Required(CONF_NAME):
                str,
                vol.Required(CONF_HOST, default='192.168.'):
                str,
                vol.Required(CONF_TOKEN):
                str,
            }),
            # description_placeholders={"device_info": "device_info"},
            errors=errors,
        )