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
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
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()
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)
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)
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
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
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
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
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
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 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