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 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(**kwargs):
     """Set mode.设置自定义模式"""
     try:
         miio_device = Device(host, token)
         miio_device.send('set_mode',
                          [kwargs["id"], kwargs["heat"], kwargs["time"]])
     except DeviceException:
         raise PlatformNotReady
Exemplo n.º 4
0
class MrBondLight(Light):
    """Representation of MrBond Airer Light."""

    def __init__(self, name, host, token):
        """Initialize the light device."""
        self._name = name or host
        self._device = Device(host, token)
        self._state = None

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

    @property
    def available(self):
        """Return true when state is known."""
        return self._state is not None

    @property
    def is_on(self):
        """Return true if light is on."""
        return self._state

    async def async_turn_on(self, **kwargs):
        """Turn the light on."""
        if await self.try_command(self.on):
            self._state = True

    async def async_turn_off(self, **kwargs):
        """Turn the light off."""
        if await self.try_command(self.off):
            self._state = False

    async def async_update(self):
        """Fetch state from the device."""
        self._state = await self.try_command(self.status)

    async def try_command(self, func):
        """Call a miio device command handling error messages."""
        try:
            result = await self.hass.async_add_job(func)
            _LOGGER.debug("Response received from miio device: %s", result)
            return result
        except Exception as exc:
            #import traceback
            # _LOGGER.error(traceback.format_exc())
            _LOGGER.error("Error on command: %s", exc)
            return None

    def status(self):
        return self._device.send('get_prop', 'led') == ['1']

    def on(self):
        return self._device.send('set_led', [1]) == ['ok']

    def off(self):
        return self._device.send('set_led', [0]) == ['ok']
 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
Exemplo n.º 7
0
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Perform the setup for Yunmi kettle."""
    from miio import Device, DeviceException

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

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

    devices = []
    try:
        device = Device(host, token)
        yumikettle = YunmiKettle(device, name)
        devices.append(yumikettle)
        devices.append(YunmiKettleSensor(yumikettle, CURRENT_TEMPE))
        devices.append(YunmiKettleSensor(yumikettle, SETUP_TEMPE))
        devices.append(YunmiKettleSensor(yumikettle, TDS))
        devices.append(YunmiKettleSensor(yumikettle, WATER_REMAIN_TIME))

    except DeviceException:
        _LOGGER.exception('Fail to setup yunmi kettle')
        raise PlatformNotReady

    add_devices(devices)

    def handle_set_temp(service):
        temp = service.data.get(ATTR_TEMP, DEFAULT_TEMP)
		if int(temp) < 30 or int(temp) > 90:
			return
        _LOGGER.info("yunmi kettle service call data: %s", int(temp))
        result = device.send('set_tempe_setup', [1, int(temp)])
		yumikettle.update()
Exemplo n.º 8
0
def test_timeout_retry(mocker):
    send = mocker.patch("miio.miioprotocol.MiIOProtocol.send")
    d = Device("127.0.0.1", "68ffffffffffffffffffffffffffffff", timeout=4)
    assert d._protocol._timeout == 4
    d.send("fake_command", [], 1)
    send.assert_called_with("fake_command", [], 1, extra_parameters=None)
    d.send("fake_command", [])
    send.assert_called_with("fake_command", [], 3, extra_parameters=None)

    class CustomDevice(Device):
        retry_count = 5
        timeout = 1

    d2 = CustomDevice("127.0.0.1", "68ffffffffffffffffffffffffffffff")
    assert d2._protocol._timeout == 1
    d2.send("fake_command", [])
    send.assert_called_with("fake_command", [], 5, extra_parameters=None)
def main():
    print('this message is from main function')
    device = Device(host, token)
    data = {}
    print('send get prop')
    #    params = {"tds_out", "temperature", "f1_totalflow", "f1_totaltime", "f1_usedflow", "f1_usedtime", "f2_totalflow", "f2_totaltime", "f2_usedflow", "f2_usedtime", "run_status", "rinse", "tds_warn_thd", "tds_out_avg" }
    properties = AVAILABLE_PROPERTIES_COMMON
    _props_per_request = 1
    _props = properties.copy()
    values = []
    while _props:
        status = device.send("get_prop", _props[:_props_per_request])
        _props[:] = _props[_props_per_request:]
        print('send get prop finished ', status)
Exemplo n.º 10
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)
Exemplo n.º 11
0
class VioMiWasher(FanEntity):
    def __init__(self, name, host, token):
        self._name = name or host
        self._device = Device(host, token)
        self._attrs = None
        self._state = False
        self._mode = DEFAULT_WASH_MODE
        self._skip_update = False

    @property
    def supported_features(self):
        """Flag supported features."""
        return SUPPORT_SET_SPEED

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

    @property
    def icon(self):
        """Return the icon to use for device if any."""
        return 'mdi:washing-machine'

    @property
    def available(self):
        """Return true when state is known."""
        return self._attrs is not None

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

    @property
    def speed_list(self):
        """Get the list of available speeds."""
        return WASH_MODES

    @property
    def speed(self):
        """Return the current speed."""
        return self._mode

    @property
    def is_on(self):
        """Return true if device is on."""
        return self._state

    async def async_update(self):
        """Fetch state from the device."""
        if self._skip_update:
            self._skip_update = False
            return

        attrs = await self.try_command(self.status)
        self._state = attrs is not None and attrs['wash_status'] == 1 and (
            (attrs['wash_process'] > 0 and attrs['wash_process'] < 7)
            or attrs['appoint_time'])
        self._attrs = attrs
        # if self._state: # 仅做开启状态时获取模式
        #     program = attrs['program']
        #     dry_mode = program == 'dry' or program == 'weak_dry' or attrs['DryMode'] != 0
        #     self._mode = ('预约' if attrs['appoint_time'] else '立即') + ('洗烘' if dry_mode else '洗衣')

    async def async_turn_on(self, speed=None, **kwargs):
        """Turn the device on."""
        if speed:
            await self.async_set_speed(speed)
            return
        result = await self.try_command(self.on)
        if result:
            self._state = True
            self._skip_update = True

    async def async_turn_off(self, **kwargs):
        """Turn the device off."""
        result = await self.try_command(self.off)
        if result:
            self._state = False
            self._skip_update = True

    async def async_set_speed(self, speed):
        """Set the speed of the fan."""
        _LOGGER.debug("Setting washer mode to: %s", speed)
        self._mode = speed  # if speed in WASH_MODES else DEFAULT_WASH_MODE

    async def try_command(self, func):
        """Call a miio device command handling error messages."""
        try:
            result = await self.hass.async_add_job(func)
            _LOGGER.debug("Response received from miio device: %s", result)
            return result
        except Exception as exc:
            #import traceback
            # _LOGGER.error(traceback.format_exc())
            _LOGGER.error("Error on command: %s", exc)
            return None

    def status(self):
        """Retrieve properties."""
        props = [
            "program",
            "wash_process",
            "wash_status",
            # "water_temp",
            # "rinse_status",
            # "spin_level",
            "remain_time",
            "appoint_time",
            # "be_status",
            # "run_status",
            "DryMode",
            # "child_lock"
        ]
        attrs = {'dash_extra_forced': True, 'genie_deviceType': 'washmachine'}
        for prop in props:
            value = self._device.send("get_prop", [prop])
            attrs[prop] = value[0] if len(value) else None

        dash_name = WASH_PROGRAMS[attrs['program']]
        if attrs['DryMode']:
            dash_name += '+烘'
        remain_time = attrs['remain_time']
        if remain_time:
            dash_name += ' ' + str(remain_time)
        appoint_time = attrs['appoint_time']
        if appoint_time:
            dash_name += '/' + str(appoint_time)
        attrs['dash_name'] = dash_name

        return attrs

    def on(self):
        if self._attrs['program'] != 'goldenwash' or self._attrs[
                'wash_process'] == 7:
            self.send("set_wash_program", 'goldenwash')

        dry_mode = 30721 if self._mode.endswith('烘') else 0
        if self._attrs['DryMode'] != dry_mode:
            self.send("SetDryMode", dry_mode)

        if self._mode.startswith('预约'):
            now = datetime.datetime.now()
            hour = now.hour
            if now.minute > 10:
                hour += 1
            if hour <= APPOINT_CLOCK - APPOINT_MIN:
                appoint_time = APPOINT_CLOCK - hour
            elif hour >= APPOINT_CLOCK + 24 - APPOINT_MAX:
                appoint_time = APPOINT_CLOCK + 24 - hour
            else:
                appoint_time = 0
        else:
            appoint_time = 0

        if appoint_time:
            result = self.send("set_appoint_time", appoint_time)
        else:
            result = self.send("set_wash_action", 1)
        return result == ['ok']

    def off(self):
        return self.send('set_wash_action', 2) == ['ok']

    def send(self, command, param):
        _LOGGER.debug('Send command: %s=%s', command, param)
        return self._device.send(command, [param])
    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:
                # Reservation
                __current_operation = STATE_1
                __work_status_cn = "Reservation"
            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:
                # Congee
                __mode_en = MODE_15
                __mode_cn = "Congee"
            elif mode == 16:
                # Edible bird's nest
                __mode_en = MODE_16
                __mode_cn = "Edible bird's nest"
            elif mode == 17:
                # Hotpot
                __mode_en = MODE_17
                __mode_cn = "Hotpot"
            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:
                # Ganoderma
                __mode_en = MODE_24
                __mode_cn = "Ganoderma"
            elif mode == 25:
                # Disinfect
                __mode_en = MODE_25
                __mode_cn = "Дезинфицировать"
            elif mode == 26:
                # Sweet soup
                __mode_en = MODE_26
                __mode_cn = "Sweet soup"
            elif mode == 1:
                # Custom
                __mode_en = MODE_1
                __mode_cn = "Custom1"
            elif mode == 2:
                # Custom
                __mode_en = MODE_2
                __mode_cn = "Custom2"
            elif mode == 3:
                # 自定义
                __mode_en = MODE_3
                __mode_cn = "Custom3"
            elif mode == 4:
                # 自定义
                __mode_en = MODE_4
                __mode_cn = "Custom4"
            elif mode == 5:
                # 自定义
                __mode_en = MODE_5
                __mode_cn = "Custom5"
            elif mode == 6:
                # 自定义
                __mode_en = MODE_6
                __mode_cn = "Custom6"
            elif mode == 7:
                # 自定义
                __mode_en = MODE_7
                __mode_cn = "Custom7"
            elif mode == 8:
                # 自定义
                __mode_en = MODE_8
                __mode_cn = "Custom8"

            __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
Exemplo n.º 13
0
class VioMiWasher(FanEntity, RestoreEntity):

    def __init__(self, name, host, token):
        self._name = name or host
        self._device = Device(host, token)
        self._status = {'dash_extra_forced': True,
                        'genie_deviceType': 'washmachine'}
        self._state = None
        self._skip_update = False
        self._dry_mode = 0
        self._appoint_time = 0

    async def async_added_to_hass(self):
        await super().async_added_to_hass()
        last_state = await self.async_get_last_state()
        _LOGGER.debug("async_added_to_hass: %s", last_state)
        if last_state:
            self._appoint_time = int(last_state.attributes.get('direction') == 'reverse')
            self._dry_mode = int(last_state.attributes.get('oscillating'))
            _LOGGER.debug("Restore state: dry_mode=%s, appoint_time=%s", self._dry_mode, self._appoint_time)

    @property
    def supported_features(self):
        """Flag supported features."""
        return SUPPORT_SET_SPEED | SUPPORT_OSCILLATE | SUPPORT_DIRECTION

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

    @property
    def icon(self):
        """Return the icon to use for device if any."""
        return 'mdi:washing-machine'

    @property
    def available(self):
        """Return true when state is known."""
        return self._state is not None

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

    def update(self):
        """Fetch state from the device."""
        if self._skip_update:
            self._skip_update = False
            return

        status = self._status
        try:
            for prop in WASHER_PROPS:
                status[prop] = self._device.send('get_prop', [prop])[0]
            self._state = status['wash_status'] == 1 and (
                (status['wash_process'] > 0 and status['wash_process'] < 7) or status['appoint_time'] != 0)
        except Exception as exc:
            _LOGGER.error("Error on update: %s", exc)
            self._state = None

        if self._state:  # Update dash name for status
            dash_name = '剩' + str(status['remain_time']) + '分'
            appoint_time = status['appoint_time']
            if appoint_time:
                dash_name += '/' + str(appoint_time) + '时'
            if status['DryMode']:
                dash_name += '+烘'
            self._status['dash_name'] = dash_name
        elif 'dash_name' in status:
            del status['dash_name']

    @property
    def is_on(self):
        """Return true if device is on."""
        return self._state

    def turn_on(self, speed=None, **kwargs):
        """Turn the device on."""
        _LOGGER.debug('turn_on: speed=%s, kwargs=%s', speed, kwargs)

        # Turn up
        if speed:
            self.set_speed(speed)
        else:
            self.set_wash_program(self._status.get('program') or 'goldenwash')
        time.sleep(1)

        # Set dry mode
        dry_mode = DEFAULT_DRY_MODE if self._dry_mode == 1 else self._dry_mode
        if self._status.get('DryMode') != dry_mode:
            if not self.control("SetDryMode", dry_mode):
                return
            time.sleep(1)

        # Calc appoint time
        appoint_time = self._appoint_time
        if appoint_time < 0:
            appoint_clock = -appoint_time
            now = datetime.datetime.now()
            hour = now.hour
            if now.minute > 10:
                hour += 1
            if hour <= appoint_clock - APPOINT_MIN:
                appoint_time = appoint_clock - hour
            elif hour >= appoint_clock + 24 - APPOINT_MAX:
                appoint_time = appoint_clock + 24 - hour
            else:
                appoint_time = 0

        if self.control('set_appoint_time' if appoint_time else 'set_wash_action', appoint_time or 1):
            self._state = True
            self._skip_update = True

    def turn_off(self, **kwargs):
        """Turn the device off."""
        if self.control('set_wash_action', 2):
            self._state = False
            self._skip_update = True

    @property
    def speed_list(self):
        """Get the list of available speeds."""
        return list(WASHER_PROGS.values())

    @property
    def speed(self):
        """Return the current speed."""
        return WASHER_PROGS.get(self._status.get('program'))

    def set_speed(self, speed):
        """Set the speed of the fan."""
        _LOGGER.debug('set_speed: %s', speed)

        for program in WASHER_PROGS:
            if program == speed or WASHER_PROGS[program] == speed:
                self.set_wash_program(program)
                return

        for control in speed.split(','):
            params = control.split('=')
            if len(params) == 2:
                if params[0] == 'program' or params[0] == 'set_wash_program':
                    if not self.set_wash_program(params[1]):
                        return
                elif params[0] == 'dry_mode':
                    # self.oscillate(params[1])
                    self._dry_mode = int(params[1])
                elif params[0] == 'appoint_time':
                    # self.set_direction(params[1])
                    self._appoint_time = int(params[1])
                elif params[0] == 'appoint_clock':
                    # self.set_direction('-' + params[1])
                    self._appoint_time = -int(params[1])
                elif not self.control(params[0], params[1]):  # Custom command
                    return
            else:
                _LOGGER.error("Invalid speed format:%s", params)

    @property
    def oscillating(self):
        """Return the oscillation state."""
        return bool(self._dry_mode)

    def oscillate(self, oscillating):
        """Oscillate the fan."""
        self._dry_mode = int(oscillating)
        _LOGGER.debug("oscillate: dry_mode=%s", self._dry_mode)

    @property
    def current_direction(self):
        """Return the current direction of the fan."""
        return 'reverse' if self._appoint_time else 'forward'

    def set_direction(self, direction):
        """Set the direction of the fan."""
        self._appoint_time = DEFAULT_APPOINT_TIME if direction == 'reverse' else int(direction)
        _LOGGER.debug("set_direction: appoint_time=%s", self._appoint_time)

    def control(self, name, value):
        _LOGGER.debug('Waher control: %s=%s', name, value)
        try:
            return self._device.send(name, [value]) == ['ok']
        except Exception as exc:
            _LOGGER.error("Error on control: %s", exc)
            return None

    def set_wash_program(self, program):
        if self.control('set_wash_program', program):
            self._status['program'] = program
            self._skip_update = True
            return True
        return False
Exemplo n.º 14
0
class BathHeaterEntity(MiioEntity, FanEntity):
    def __init__(self, config, mode='warmwind', parent=None):
        name = config[CONF_NAME]
        host = config[CONF_HOST]
        token = config[CONF_TOKEN]
        model = config.get(CONF_MODEL)
        _LOGGER.info('Initializing with host %s (token %s...)', host, token[:5])

        self._device = Device(ip=host, token=token)
        super().__init__(name, self._device)
        self._unique_id = f'{self._miio_info.model}-{self._miio_info.mac_address}-{mode}'
        self._mode = mode
        self._parent = parent
        self._supported_features = SUPPORT_SET_SPEED
        self._props = [
            'power', 'bright', 'delayoff', 'nl_br', 'nighttime',
            'bh_mode', 'bh_delayoff', 'light_mode', 'fan_speed_idx',
        ]
        if model in ['yeelink.bhf_light.v1']:
            self._props.extend(['temperature', 'humidity', 'aim_temp'])
        self._state_attrs.update({
            'mode': mode,
            'parent_entity': parent.mode if parent else mode,
            'entity_class': self.__class__.__name__,
        })
        self._mode_speeds = {}

    async def async_added_to_hass(self):
        cfg = self.custom_config(with_parent=True) or {}
        if cfg.get('support_oscillate'):
            self._supported_features |= SUPPORT_OSCILLATE
            if 'swing_action' not in self._props:
                self._props.append('swing_action')
        if cfg.get('support_direction'):
            self._supported_features |= SUPPORT_DIRECTION
            if 'swing_angle' not in self._props:
                self._props.append('swing_angle')

    @property
    def mode(self):
        return self._mode

    async def async_update(self):
        if self._parent and self._parent.available:
            self._available = True
            self._state_attrs.update(self._parent.device_state_attributes)
            self._state_attrs.update({
                'mode': self._mode,
                'entity_class': self.__class__.__name__,
            })
        else:
            await super().async_update()
        if self._available:
            attrs = self._state_attrs
            self._state = attrs.get('bh_mode') == self._mode
            if 'fan_speed_idx' in attrs:
                fls = '%05d' % int(attrs.get('fan_speed_idx', 0))
                self._mode_speeds = {
                    'drying_cloth': fls[0],
                    'coolwind': fls[1],
                    'drying': fls[2],
                    'venting': fls[3],
                    'warmwind': fls[4],
                }

    async def async_turn_on(self, speed=None, **kwargs):
        _LOGGER.debug('Turning on for %s. speed: %s %s', self._name, speed, kwargs)
        if speed == SPEED_OFF:
            await self.async_turn_off()
        else:
            if not self._state:
                result = await self.async_command('set_bh_mode', [self._mode])
                if result:
                    self._state = True
                    self.update_attrs({
                        'bh_mode': self._mode,
                    })
            if speed:
                await self.async_set_speed(speed)

    async def async_turn_off(self, **kwargs):
        _LOGGER.debug('Turning off for %s.', self._name)
        result = await self.async_command('stop_bath_heater')
        if result:
            self._state = False
            self.update_attrs({
                'bh_mode': 'bh_off',
            })

    @property
    def speed(self):
        spd = int(self._mode_speeds.get(self._mode, 0))
        if spd >= 3:
            return SPEED_FIERCE
        elif spd >= 2:
            return SPEED_HIGH
        elif spd >= 1:
            return SPEED_MEDIUM
        return SPEED_LOW

    @property
    def mode_speeds(self):
        return self._mode_speeds

    @property
    def speed_list(self):
        fls = [SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH]
        if self._mode == 'venting':
            fls.append(SPEED_FIERCE)
        return fls

    @staticmethod
    def speed_to_gears(speed=None):
        spd = 0
        if speed == SPEED_MEDIUM:
            spd = 1
        if speed == SPEED_HIGH:
            spd = 2
        if speed == SPEED_FIERCE:
            spd = 9
        return spd

    def set_speed(self, speed):
        spd = self.speed_to_gears(speed)
        _LOGGER.debug('Setting speed for %s: %s(%s)', self._name, speed, spd)
        self._device.send('set_gears_idx', [spd])

    async def async_set_speed(self, speed):
        spd = self.speed_to_gears(speed)
        _LOGGER.debug('Setting speed for %s: %s(%s)', self._name, speed, spd)
        result = await self.async_command('set_gears_idx', [spd])
        if result:
            self._mode_speeds.update({
                self._mode: spd,
            })
            if 'gears' in self._state_attrs:
                self.update_attrs({
                    'gears': spd,
                })
            if 'fan_speed_idx' in self._state_attrs:
                lst = [str(v) for k, v in self._mode_speeds.items()]
                self.update_attrs({
                    'fan_speed_idx': ''.join(lst).lstrip('0') or '0',
                })

    @property
    def oscillating(self):
        return self._state_attrs.get('swing_action') == 'swing'

    async def async_oscillate(self, oscillating: bool):
        act = 'swing' if oscillating else 'stop'
        _LOGGER.debug('Setting oscillating for %s: %s(%s)', self._name, act, oscillating)
        result = await self.async_command('set_swing', [act, 0])
        if result:
            self.update_attrs({
                'swing_action': act,
            })

    @property
    def current_direction(self):
        if int(self._state_attrs.get('swing_angle', 0)) > 90:
            return DIRECTION_REVERSE
        return DIRECTION_FORWARD

    async def async_set_direction(self, direction: str):
        act = 'angle'
        try:
            num = int(direction)
        except (TypeError, ValueError):
            num = 0
        if num < 1:
            num = 120 if direction == DIRECTION_REVERSE else 90
        _LOGGER.debug('Setting direction for %s: %s(%s)', self._name, direction, num)
        result = await self.async_command('set_swing', [act, num])
        if result:
            self.update_attrs({
                'swing_action': act,
                'swing_angle': num,
            })

    def update_attrs(self, attrs, update_parent=True):
        self._state_attrs.update(attrs or {})
        if update_parent and self._parent and hasattr(self._parent, 'update_attrs'):
            getattr(self._parent, 'update_attrs')(attrs or {}, False)
        return self._state_attrs
Exemplo n.º 15
0
def test_default_timeout_and_retry(mocker):
    send = mocker.patch("miio.miioprotocol.MiIOProtocol.send")
    d = Device("127.0.0.1", "68ffffffffffffffffffffffffffffff")
    assert d._protocol._timeout == 5
    d.send(command="fake_command", parameters=[])
    send.assert_called_with("fake_command", [], 3, extra_parameters=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
Exemplo n.º 17
0
class BathHeaterEntity(MiioEntity, FanEntity):
    def __init__(self, config, mode='warmwind', parent=None):
        name = config[CONF_NAME]
        host = config[CONF_HOST]
        token = config[CONF_TOKEN]
        model = config.get(CONF_MODEL)
        _LOGGER.info('Initializing with host %s (token %s...)', host,
                     token[:5])

        self._device = Device(host, token)
        super().__init__(name, self._device)
        self._unique_id = f'{self._miio_info.model}-{self._miio_info.mac_address}-{mode}'
        self._mode = mode
        self._parent = parent
        self._supported_features = SUPPORT_SET_SPEED
        self._props = [
            'power',
            'bright',
            'delayoff',
            'nl_br',
            'nighttime',
            'bh_mode',
            'bh_delayoff',
            'light_mode',
            'fan_speed_idx',
        ]
        if model in ['yeelink.bhf_light.v1']:
            self._props.append('temperature')
            self._props.append('humidity')
            self._props.append('aim_temp')
        self._state_attrs.update({
            'mode': mode,
            'entity_class': self.__class__.__name__,
        })
        self._mode_speeds = {}

    @property
    def mode(self):
        return self._mode

    async def async_update(self):
        if self._parent and self._parent.available:
            self._available = True
            self._state_attrs.update(self._parent.device_state_attributes)
            self._state_attrs.update({
                'mode': self._mode,
                'entity_class': self.__class__.__name__,
            })
        else:
            await super().async_update()
        if self._available:
            attrs = self._state_attrs
            self._state = attrs.get('bh_mode') == self._mode
            if 'fan_speed_idx' in attrs:
                fls = '%05d' % int(attrs.get('fan_speed_idx', 0))
                self._mode_speeds = {
                    'drying_cloth': fls[0],
                    'coolwind': fls[1],
                    'drying': fls[2],
                    'venting': fls[3],
                    'warmwind': fls[4],
                }

    async def async_turn_on(self, speed=None, **kwargs):
        _LOGGER.debug('Turning on for %s. speed: %s %s', self._name, speed,
                      kwargs)
        if speed == SPEED_OFF:
            await self.async_turn_off()
        else:
            if not self._state:
                result = await self.async_command('set_bh_mode', [self._mode])
                if result:
                    self._state = True
                    self.update_attrs({
                        'bh_mode': self._mode,
                    })
            if speed:
                await self.async_set_speed(speed)

    async def async_turn_off(self, **kwargs):
        _LOGGER.debug('Turning off for %s.', self._name)
        result = await self.async_command('stop_bath_heater')
        if result:
            self._state = False
            self.update_attrs({
                'bh_mode': 'bh_off',
            })

    @property
    def speed(self):
        spd = int(self._mode_speeds.get(self._mode, 0))
        if spd >= 3:
            return SPEED_FIERCE
        elif spd >= 2:
            return SPEED_HIGH
        elif spd >= 1:
            return SPEED_MEDIUM
        return SPEED_LOW

    @property
    def mode_speeds(self):
        return self._mode_speeds

    @property
    def speed_list(self):
        fls = [SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH]
        if self._mode == 'venting':
            fls.append(SPEED_FIERCE)
        return fls

    @staticmethod
    def speed_to_gears(speed=None):
        spd = 0
        if speed == SPEED_MEDIUM:
            spd = 1
        if speed == SPEED_HIGH:
            spd = 2
        if speed == SPEED_FIERCE:
            spd = 9
        return spd

    def set_speed(self, speed):
        spd = self.speed_to_gears(speed)
        _LOGGER.debug('Setting speed for %s: %s(%s)', self._name, speed, spd)
        self._device.send('set_gears_idx', [spd])

    async def async_set_speed(self, speed):
        spd = self.speed_to_gears(speed)
        _LOGGER.debug('Setting speed for %s: %s(%s)', self._name, speed, spd)
        result = await self.async_command('set_gears_idx', [spd])
        if result:
            self._mode_speeds.update({
                self._mode: spd,
            })
            if 'gears' in self._state_attrs:
                self.update_attrs({
                    'gears': spd,
                })
            if 'fan_speed_idx' in self._state_attrs:
                lst = [str(v) for k, v in self._mode_speeds.items()]
                self.update_attrs({
                    'fan_speed_idx':
                    ''.join(lst).lstrip('0') or '0',
                })

    def set_direction(self, direction):
        pass

    def oscillate(self, oscillating):
        pass

    def update_attrs(self, attrs, update_parent=True):
        self._state_attrs.update(attrs or {})
        if update_parent and self._parent and hasattr(self._parent,
                                                      'update_attrs'):
            self._parent.update_attrs(attrs or {}, False)
        return self._state_attrs
Exemplo n.º 18
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
Exemplo n.º 19
0
def async_setup(hass, config):
    #def setup(hass, config):
    """Set up the Xiaomi Gateway miio platform."""
    from miio import Device, DeviceException

    host = config[DOMAIN].get(CONF_HOST)
    token = config[DOMAIN].get(CONF_TOKEN)

    if host is None or token is None:
        _LOGGER.error("Platform %s not configured", DOMAIN)
        return False

    if DOMAIN not in hass.data:
        hass.data[DOMAIN] = {}
        hass.data[DOMAIN]['device'] = None
        hass.data[DOMAIN]['sid'] = []
        hass.data[DOMAIN]['light'] = {"name": [], "sid": [], "device": []}
        hass.data[DOMAIN]['switch'] = {"name": [], "sid": [], "device": []}
        hass.data[DOMAIN]['radio'] = {
            "name": None,
            "source_list": [],
            "program_list": []
        }
        hass.data[DOMAIN]['power'] = {}
    else:
        hass.data[DOMAIN]['device'] = None
        hass.data[DOMAIN]['sid'].clear()

        hass.data[DOMAIN]['light']["name"].clear()
        hass.data[DOMAIN]['light']["sid"].clear()

        hass.data[DOMAIN]['switch']["name"].clear()
        hass.data[DOMAIN]['switch']["sid"].clear()

        hass.data[DOMAIN]['radio']["name"] = None
        hass.data[DOMAIN]['radio']["source_list"].clear()
        hass.data[DOMAIN]['radio']["program_list"].clear()

        hass.data[DOMAIN]['power'].clear()

    async def xiaomigateway_discovered(service, discovery_info):
        """Perform action when Xiaomi Gateway device(s) has been found."""
        # We don't need to do anything here, the purpose of Home Assistant's
        # discovery service is to just trigger loading of this
        # component, and then its own discovery process kicks in.

    _LOGGER.info(
        "Initializing Xiaomi Gateway with host %s (with token is ...%s)", host,
        token)

    try:
        miio_device = Device(host, token)
        device_info = miio_device.info()
        if device_info is None:
            _LOGGER.error("Device not ready")
            return False

        sid_list = []
        sid_list = miio_device.send('get_device_prop',
                                    ['lumi.0', 'device_list'])
        cnt = len(sid_list)
        i = 0
        while i < cnt:
            buf = []
            buf = str(sid_list[i])
            if len(buf) < 6:
                sid_list.pop(i)
                cnt = cnt - 1
            else:
                buf = buf[:5]
                if buf != 'lumi.':
                    sid_list.pop(i)
                    cnt = cnt - 1
                else:
                    i = i + 1
        hass.data[DOMAIN]['device'] = miio_device
        hass.data[DOMAIN]['sid'] = []

        for sid in sid_list:
            hass.data[DOMAIN]['sid'].append(sid)

# Create list of load components
        components = []

        # List of Light

        i = 0
        if len(config[DOMAIN]['light'][0]) > 0:
            for item in config[DOMAIN]['light']:
                item = config[DOMAIN]['light'][i]
                sid = item['sid']
                _LOGGER.debug("Light SID: %s", sid)
                if sid[:5] != "lumi.":
                    sid = "lumi." + sid
                _LOGGER.debug("Light SID: %s Count: %d", sid,
                              hass.data[DOMAIN]['sid'].count(sid))
                if hass.data[DOMAIN]['sid'].count(sid) == 1:
                    if sid[:14] != "lumi.158d0003e":
                        _LOGGER.error("Sid %s is not Aqara LED Bulb")
                        continue
                    if components.count('light') == 0:
                        _LOGGER.debug("Add Aqara LED Bulb %s", sid)
                        components.append('light')
# Add sid
                    hass.data[DOMAIN]['light']['sid'].append(sid)
                    name = config[DOMAIN]['light'][i].get(CONF_NAME, None)
                    if name is None:
                        name = DEFAULT_NAME_LIGHT + "." + sid
# Add name
                    if hass.data[DOMAIN]['light']['name'].count(name) > 0:
                        name = name + "." + sid
                    hass.data[DOMAIN]['light']['name'].append(name)
                    # Create socket for each light
                    try:
                        light_device = Device(host, token)
                        light_info = light_device.info()
                        if light_info is None:
                            # If socket not open, choise first opened socket (miio_device)
                            _LOGGER.error("Device not ready")
                            hass.data[DOMAIN]['light']['device'].append(
                                miio_device)
                        else:
                            # Else choise opened socket
                            hass.data[DOMAIN]['light']['device'].append(
                                light_device)
                    except DeviceException as light_exc:
                        _LOGGER.error("Error open socket for light:",
                                      light_exc)
                i = i + 1

# List of Switch

        i = 0
        if len(config[DOMAIN]['switch'][0]) > 0:
            for item in config[DOMAIN]['switch']:
                item = config[DOMAIN]['switch'][i]
                sid = item['sid']
                if sid[:5] != "lumi.":
                    sid = "lumi." + sid
                _LOGGER.debug("Switch SID: %s Count: %d", sid,
                              hass.data[DOMAIN]['sid'].count(sid))
                if hass.data[DOMAIN]['sid'].count(sid) == 1:
                    _LOGGER.debug("Check Switch")
                    if sid[:14] != "lumi.158d0003c":
                        _LOGGER.error("Sid %s is not Aqara Relay")
                        continue
                    result = miio_device.send('get_device_prop_exp',
                                              [[sid, 'load_power']])
                    load_power = result[0][0]
                    if load_power < 0.0:
                        continue
                    _LOGGER.debug("Switch GOOD")
                    if components.count('switch') == 0:
                        _LOGGER.debug("Add Aqara Relay %s", sid)
                        components.append('switch')
# Add sid
                    hass.data[DOMAIN]['switch']['sid'].append(sid)
                    name = config[DOMAIN]['switch'][i].get(CONF_NAME, None)
                    # Add name
                    if name is None:
                        name = DEFAULT_NAME_SWITCH + "." + sid
                    if hass.data[DOMAIN]['switch']['name'].count(name) > 0:
                        name = name + "." + sid
                    hass.data[DOMAIN]['switch']['name'].append(name)
                    # Create socket for each switch
                    try:
                        switch_device = Device(host, token)
                        switch_info = switch_device.info()
                        if switch_info is None:
                            # If socket not open, choise first opened socket (miio_device)
                            _LOGGER.error("Device not ready")
                            hass.data[DOMAIN]['switch']['device'].append(
                                miio_device)
                        else:
                            # Else choise opened socket
                            hass.data[DOMAIN]['switch']['device'].append(
                                switch_device)
                    except DeviceException as switch_exc:
                        _LOGGER.error("Error open socket for switch:",
                                      switch_exc)
                i = i + 1

# Radio

        if len(config[DOMAIN]['media_player'][0]) > 0:
            name = None
            name = config[DOMAIN]['media_player'][0].get(CONF_NAME)
            if (name) is None:
                name = DEFAULT_NAME_RADIO
            _LOGGER.debug("MEDIA_PLAYER: %s", config[DOMAIN]['media_player'])
            hass.data[DOMAIN]['radio']['name'] = name
            hass.data[DOMAIN]['radio']['source_list'] = config[DOMAIN][
                'media_player'][0].get('source_list')
            hass.data[DOMAIN]['radio']['program_list'] = config[DOMAIN][
                'media_player'][0].get('program_list')

            components.append('media_player')

        _LOGGER.debug("Load Components: %s", components)
        for item in components:
            discovery.load_platform(hass, item, DOMAIN, {}, config)

        def stop_xiaomigateway(event):
            """Stop XiaomiGateway Socket."""
            _LOGGER.info("Shutting down XiaomiGateway")
            hass.data[DOMAIN].clear()

    except DeviceException:
        _LOGGER.error("Can't init platform")
        return False
    return True
    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