async def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the sensor from config.""" if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} host = config.get(CONF_HOST) token = config.get(CONF_TOKEN) mapping = config.get(CONF_MAPPING) params = config.get(CONF_CONTROL_PARAMS) mappingnew = {} main_mi_type = None this_mi_type = [] for t in MAP[TYPE]: if mapping.get(t): this_mi_type.append(t) if 'main' in (params.get(t) or ""): main_mi_type = t if main_mi_type or type(params) == OrderedDict: for k, v in mapping.items(): for kk, vv in v.items(): mappingnew[f"{k[:10]}_{kk}"] = vv _LOGGER.info("Initializing %s with host %s (token %s...)", config.get(CONF_NAME), host, token[:5]) if type(params) == OrderedDict: miio_device = MiotDevice(ip=host, token=token, mapping=mapping) else: miio_device = MiotDevice(ip=host, token=token, mapping=mappingnew) try: if host == DUMMY_IP and token == DUMMY_TOKEN: raise DeviceException device_info = miio_device.info() model = device_info.model _LOGGER.info( "%s %s %s detected", model, device_info.firmware_version, device_info.hardware_version, ) except DeviceException as de: if not config.get(CONF_CLOUD): _LOGGER.warn(de) raise PlatformNotReady else: if not (di := config.get('cloud_device_info')): _LOGGER.error( f"未能获取到设备信息,请删除 {config.get(CONF_NAME)} 重新配置。") raise PlatformNotReady else: device_info = dev_info(di['model'], di['mac'], di['fw_version'], "")
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the sensor from config.""" if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} host = config.get(CONF_HOST) token = config.get(CONF_TOKEN) mapping = config.get(CONF_MAPPING) _LOGGER.info("Initializing %s with host %s (token %s...)", config.get(CONF_NAME), host, token[:5]) try: # miio_device = Device(host, token) miio_device = MiotDevice(ip=host, token=token, mapping=mapping) device_info = miio_device.info() model = device_info.model _LOGGER.info( "%s %s %s detected", model, device_info.firmware_version, device_info.hardware_version, ) device = MiotHumidifier(miio_device, config, device_info, hass) except DeviceException: raise PlatformNotReady hass.data[DATA_KEY][host] = device async_add_devices([device], update_before_add=True)
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the sensor from config.""" if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} host = config.get(CONF_HOST) token = config.get(CONF_TOKEN) mapping = config.get(CONF_MAPPING) params = config.get(CONF_CONTROL_PARAMS) mappingnew = {} main_mi_type = None this_mi_type = [] for t in MAP[TYPE]: if params.get(t): this_mi_type.append(t) if 'main' in (params.get(t) or ""): main_mi_type = t if main_mi_type or type(params) == OrderedDict: for k, v in mapping.items(): for kk, vv in v.items(): mappingnew[f"{k[:10]}_{kk}"] = vv _LOGGER.info("Initializing %s with host %s (token %s...)", config.get(CONF_NAME), host, token[:5]) try: if type(params) == OrderedDict: miio_device = MiotDevice(ip=host, token=token, mapping=mapping) else: miio_device = MiotDevice(ip=host, token=token, mapping=mappingnew) device_info = miio_device.info() model = device_info.model _LOGGER.info( "%s %s %s detected", model, device_info.firmware_version, device_info.hardware_version, ) device = MiotCover(miio_device, config, device_info, hass, main_mi_type) except DeviceException as de: _LOGGER.warn(de) raise PlatformNotReady _LOGGER.info(f"{main_mi_type} is the main device of {host}.") hass.data[DOMAIN]['miot_main_entity'][host] = device hass.data[DOMAIN]['entities'][device.unique_id] = device async_add_devices([device], update_before_add=True) else: _LOGGER.error(f"cover只能作为主设备!请检查{config.get(CONF_NAME)}配置")
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the fan from config.""" if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} host = config.get(CONF_HOST) token = config.get(CONF_TOKEN) mapping = config.get(CONF_MAPPING) params = config.get(CONF_CONTROL_PARAMS) mappingnew = {} main_mi_type = None this_mi_type = [] for t in MAP[TYPE]: if params.get(t): this_mi_type.append(t) if 'main' in (params.get(t) or ""): main_mi_type = t if main_mi_type or type(params) == OrderedDict: for k, v in mapping.items(): for kk, vv in v.items(): mappingnew[f"{k[:10]}_{kk}"] = vv _LOGGER.info("Initializing %s with host %s (token %s...)", config.get(CONF_NAME), host, token[:5]) try: if type(params) == OrderedDict: miio_device = MiotDevice(ip=host, token=token, mapping=mapping) else: miio_device = MiotDevice(ip=host, token=token, mapping=mappingnew) device_info = dev_info("aaa", "bbb", "ccc", "ddd") device = MiotMediaPlayer(miio_device, config, device_info, hass, main_mi_type) except DeviceException as de: _LOGGER.warn(de) raise PlatformNotReady hass.data[DATA_KEY][host] = device async_add_devices([device], update_before_add=True) else: _LOGGER.error("media player只能作为主设备!") pass
def __init__(self, config): 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]) if model in ['yeelink.light.fancl1', 'YLFD02YL']: self.mapping.update({ 'scenes': { 'siid': 4, 'piid': 3 }, }) self._device = MiotDevice(self.mapping, host, token) super().__init__(name, self._device) self._supported_features = SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP self._state_attrs.update({'entity_class': self.__class__.__name__}) self._brightness = None self._color_temp = None self._delay_off = None self._scenes = LIGHT_SCENES
def __init__(self, name, host, token, model): if model == BABAI_CURTAIN_BB82MJ or model == LUMI_CURTAIN_HAGL05: self._action_pause = 0 self._action_open = 1 self._action_close = 2 if model == SYNIOT_CURTAIN_SYC1: self._action_open = 0 self._action_close = 1 self._action_pause = 2 else: self._action_pause = 1 self._action_open = 2 self._action_close = 0 self._model = model self._name = name self._current_position = 0 self._target_position = 0 self._action = 0 self.miotDevice = MiotDevice(ip=host, token=token, mapping=MIOT_MAPPING[self._model]) _LOGGER.info("Init miot device: {}, {}".format(self._name, self.miotDevice))
def __init__(self, name, host, token, model): self._name = name self._current_position = 0 self._target_position = 0 self._action = 0 if model: self._model = model self._mapping = MIOT_MAPPING[model] else: self._mapping = { ATTR_MOTOR_CONTROL: {"siid": 0, "piid": 0}, ATTR_CURRENT_POSITION: {"siid": 0, "piid": 0}, ATTR_TARGET_POSITION: {"siid": 0, "piid": 0}, ATTR_PAUSE: 0, ATTR_OPEN: 0, ATTR_CLOSE: 0, } # init device self.miotDevice = MiotDevice(ip=host, token=token) _LOGGER.info("Init miot device: {}, {}".format(self._name, self.miotDevice)) # if model not config get model from miot device info if not model: self._model = self.miotDevice.info().model self._mapping = get_mapping(self._model, self._mapping)
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the sensor from config.""" if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} host = config.get(CONF_HOST) token = config.get(CONF_TOKEN) mapping = config.get(CONF_MAPPING) _LOGGER.info("Initializing %s with host %s (token %s...)", config.get(CONF_NAME), host, token[:5]) try: miio_device = MiotDevice(ip=host, token=token, mapping=mapping) device_info = miio_device.info() model = device_info.model _LOGGER.info( "%s %s %s detected", model, device_info.firmware_version, device_info.hardware_version, ) device = MiotSensor(miio_device, config, device_info) devices = [device] # for item in config['mapping']: # devices.append(MiotSubSensor(device, item)) except DeviceException as de: _LOGGER.warn(de) raise PlatformNotReady hass.data[DATA_KEY][host] = device # async_add_devices([device], update_before_add=True) async_add_devices(devices, update_before_add=True)
def __init__(self, config): 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]) if model in ['yeelink.light.fancl2', 'YLFD001']: # http://miot-spec.org/miot-spec-v2/instance?type=urn:miot-spec-v2:device:light:0000A001:yeelink-fancl2:1 self.mapping.update({ 'dalayoff': { 'siid': 3, 'piid': 11 }, }) self._device = MiotDevice(self.mapping, host, token) super().__init__(name, self._device) self._unique_id = f'{self._miio_info.model}-{self._miio_info.mac_address}-fan' self._supported_features = SUPPORT_SET_SPEED self._state_attrs.update({'entity_class': self.__class__.__name__})
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the sensor from config.""" if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} host = config.get(CONF_HOST) token = config.get(CONF_TOKEN) mapping = config.get(CONF_MAPPING) params = config.get(CONF_CONTROL_PARAMS) if params is None: params = OrderedDict() mappingnew = {} main_mi_type = None other_mi_type = [] #sensor的添加逻辑和其他实体不一样。他会把每个属性都作为实体。其他设备会作为attr for t in MAP[TYPE]: if params.get(t): other_mi_type.append(t) if 'main' in (params.get(t) or ""): main_mi_type = t try: other_mi_type.remove(main_mi_type) except: pass if main_mi_type or type(params) == OrderedDict: for k,v in mapping.items(): for kk,vv in v.items(): mappingnew[f"{k[:10]}_{kk}"] = vv _LOGGER.info("Initializing %s with host %s (token %s...)", config.get(CONF_NAME), host, token[:5]) try: if type(params) == OrderedDict: miio_device = MiotDevice(ip=host, token=token, mapping=mapping) else: miio_device = MiotDevice(ip=host, token=token, mapping=mappingnew) device_info = miio_device.info() model = device_info.model _LOGGER.info( "%s %s %s detected", model, device_info.firmware_version, device_info.hardware_version, ) device = MiotSensor(miio_device, config, device_info, hass, main_mi_type) devices = [device] # for item in config['mapping']: # devices.append(MiotSubSensor(device, item)) except DeviceException as de: _LOGGER.warn(de) raise PlatformNotReady _LOGGER.info(f"{main_mi_type} is the main device of {host}.") hass.data[DOMAIN]['miot_main_entity'][host] = device hass.data[DOMAIN]['entities'][device.unique_id] = device async_add_devices(devices, update_before_add=True) if other_mi_type: parent_device = None try: parent_device = hass.data[DOMAIN]['miot_main_entity'][host] except KeyError: _LOGGER.warning(f"{host} 的主设备尚未就绪,子设备 {TYPE} 等待主设备加载完毕后才会加载") raise PlatformNotReady # _LOGGER.error( parent_device.device_state_attributes) for k,v in mapping.items(): if k in MAP[TYPE]: for kk,vv in v.items(): mappingnew[f"{k[:10]}_{kk}"] = vv devices = [] for k in mappingnew.keys(): devices.append(MiotSubSensor(parent_device, mappingnew, params, other_mi_type[0],{'sensor_property': k})) # device = MiotSubSensor(parent_device, "switch_switch_status") async_add_devices(devices, update_before_add=True)
async def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the fan from config.""" if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} host = config.get(CONF_HOST) token = config.get(CONF_TOKEN) mapping = config.get(CONF_MAPPING) params = config.get(CONF_CONTROL_PARAMS) mappingnew = {} main_mi_type = None other_mi_type = [] for t in MAP[TYPE]: if mapping.get(t): other_mi_type.append(t) if 'main' in (params.get(t) or ""): main_mi_type = t try: other_mi_type.remove(main_mi_type) except: pass if main_mi_type or type(params) == OrderedDict: for k, v in mapping.items(): for kk, vv in v.items(): mappingnew[f"{k[:10]}_{kk}"] = vv _LOGGER.info("Initializing %s with host %s (token %s...)", config.get(CONF_NAME), host, token[:5]) if type(params) == OrderedDict: miio_device = MiotDevice(ip=host, token=token, mapping=mapping) else: miio_device = MiotDevice(ip=host, token=token, mapping=mappingnew) try: if host == DUMMY_IP and token == DUMMY_TOKEN: raise DeviceException device_info = miio_device.info() model = device_info.model _LOGGER.info( "%s %s %s detected", model, device_info.firmware_version, device_info.hardware_version, ) except DeviceException as de: if not config.get(CONF_CLOUD): _LOGGER.warn(de) raise PlatformNotReady else: try: devinfo = await get_dev_info(hass, config.get(CONF_CLOUD)['did']) device_info = dev_info(devinfo['result'][1]['value'], token, devinfo['result'][3]['value'], "") except Exception as ex: _LOGGER.error( f"Failed to get device info for {config.get(CONF_NAME)}" ) device_info = dev_info(host, token, "", "") device = MiotFan(miio_device, config, device_info, hass, main_mi_type) _LOGGER.info(f"{main_mi_type} is the main device of {host}.") hass.data[DOMAIN]['miot_main_entity'][host] = device hass.data[DOMAIN]['entities'][device.unique_id] = device async_add_devices([device], update_before_add=True) if other_mi_type: retry_time = 1 while True: if parent_device := hass.data[DOMAIN]['miot_main_entity'].get( host): break else: retry_time *= 2 if retry_time > 120: _LOGGER.error( f"The main device of {config.get(CONF_NAME)}({host}) is still not ready after 120 seconds!" ) raise PlatformNotReady else: _LOGGER.debug( f"The main device of {config.get(CONF_NAME)}({host}) is still not ready after {retry_time - 1} seconds." ) await asyncio.sleep(retry_time) for k, v in mapping.items(): if k in MAP[TYPE]: for kk, vv in v.items(): mappingnew[f"{k[:10]}_{kk}"] = vv devices = [] for item in other_mi_type: if item == 'a_l': devices.append( MiotActionList(parent_device, mapping.get(item), item)) else: devices.append( MiotSubFan(parent_device, mapping.get(item), params.get(item), item)) async_add_devices(devices, update_before_add=True)
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the fan from config.""" if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} host = config.get(CONF_HOST) token = config.get(CONF_TOKEN) mapping = config.get(CONF_MAPPING) params = config.get(CONF_CONTROL_PARAMS) mappingnew = {} main_mi_type = None other_mi_type = [] for t in MAP[TYPE]: if mapping.get(t): other_mi_type.append(t) if 'main' in (mapping.get(t) or ""): main_mi_type = t try: other_mi_type.remove(main_mi_type) except: pass if main_mi_type or type(params) == OrderedDict: for k, v in mapping.items(): for kk, vv in v.items(): mappingnew[f"{k[:10]}_{kk}"] = vv _LOGGER.info("Initializing %s with host %s (token %s...)", config.get(CONF_NAME), host, token[:5]) try: if type(params) == OrderedDict: miio_device = MiotDevice(ip=host, token=token, mapping=mapping) else: miio_device = MiotDevice(ip=host, token=token, mapping=mappingnew) device_info = miio_device.info() model = device_info.model _LOGGER.info( "%s %s %s detected", model, device_info.firmware_version, device_info.hardware_version, ) device = MiotFan(miio_device, config, device_info, hass, main_mi_type) except DeviceException as de: _LOGGER.warn(de) raise PlatformNotReady _LOGGER.info(f"{main_mi_type} is the main device of {host}.") hass.data[DOMAIN]['miot_main_entity'][host] = device hass.data[DOMAIN]['entities'][device.unique_id] = device async_add_devices([device], update_before_add=True) if other_mi_type: parent_device = None try: parent_device = hass.data[DOMAIN]['miot_main_entity'][host] except KeyError: _LOGGER.warning(f"{host} 的主设备尚未就绪,子设备 {TYPE} 等待主设备加载完毕后才会加载") raise PlatformNotReady for k, v in mapping.items(): if k in MAP[TYPE]: for kk, vv in v.items(): mappingnew[f"{k[:10]}_{kk}"] = vv devices = [] for item in other_mi_type: if item == 'a_l': devices.append( MiotActionList(parent_device, mapping.get(item), item)) else: devices.append( MiotSubLight(parent_device, mapping.get(item), params.get(item), item)) async_add_devices(devices, update_before_add=True)
async def async_step_devinfo(self, user_input=None): errors = {} hint = "" if user_input is not None: self._devtype = user_input['devtype'] self._input2['devtype'] = self._devtype self._input2[CONF_MAPPING] = user_input[CONF_MAPPING] self._input2[CONF_CONTROL_PARAMS] = user_input[CONF_CONTROL_PARAMS] # self._input2['cloud_read'] = user_input['cloud_read'] self._input2['cloud_write'] = user_input.get('cloud_write') # v = await validate_devinfo(self.hass, self._input2) v = [[], []] if v == [[], []]: try: # print(result) if not user_input.get('cloud_read') and not user_input.get( 'cloud_write'): device = MiotDevice( ip=self._input2[CONF_HOST], token=self._input2[CONF_TOKEN], mapping=list( json.loads( self._input2[CONF_MAPPING]).values())[0]) result = device.get_properties_for_mapping() return self.async_create_entry( title=self._input2[CONF_NAME], data=self._input2, ) else: if cloud := self.hass.data[DOMAIN].get( 'cloud_instance'): did = None for dev in self.hass.data[DOMAIN][ 'micloud_devices']: if dev.get( 'localip') == self._input2[CONF_HOST]: did = dev['did'] if did: self._input2['update_from_cloud'] = { 'did': did, 'userId': cloud.auth['user_id'], 'serviceToken': cloud.auth['service_token'], 'ssecurity': cloud.auth['ssecurity'], } return self.async_create_entry( title=self._input2[CONF_NAME], data=self._input2, ) else: return self.async_show_form( step_id="cloudinfo", data_schema=vol.Schema({ vol.Required('did'): str, vol.Required('userId', default=cloud.auth['user_id']): str, vol.Required('serviceToken', default=cloud.auth['service_token']): str, vol.Required('ssecurity', default=cloud.auth['ssecurity']): str, }), description_placeholders={ "device_info": "没找到 did,请手动填一下" }, errors=errors, ) else: return self.async_show_form( step_id="cloudinfo", data_schema=vol.Schema({ vol.Required('did'): str, vol.Required('userId'): str, vol.Required('serviceToken'): str, vol.Required('ssecurity'): str, }), # description_placeholders={"device_info": hint}, errors=errors, )
async def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the fan from config.""" if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} host = config.get(CONF_HOST) token = config.get(CONF_TOKEN) mapping = config.get(CONF_MAPPING) params = config.get(CONF_CONTROL_PARAMS) mappingnew = {} main_mi_type = None other_mi_type = [] for t in MAP[TYPE]: if mapping.get(t): other_mi_type.append(t) if 'main' in (params.get(t) or ""): main_mi_type = t try: other_mi_type.remove(main_mi_type) except: pass if main_mi_type or type(params) == OrderedDict: for k, v in mapping.items(): for kk, vv in v.items(): mappingnew[f"{k[:10]}_{kk}"] = vv if 'a_l' not in mapping.keys(): persistent_notification.async_create( hass, f"为了支持更多种类小爱,配置参数有变动,\n" f"请删除您的 **{config.get(CONF_NAME)}** 重新配置。谢谢\n", "Xiaomi MIoT") _LOGGER.info("Initializing %s with host %s (token %s...)", config.get(CONF_NAME), host, token[:5]) try: if type(params) == OrderedDict: miio_device = MiotDevice(ip=host, token=token, mapping=mapping) else: miio_device = MiotDevice(ip=host, token=token, mapping=mappingnew) device_info = dev_info(host, token, "", "") device = MiotMediaPlayer(miio_device, config, device_info, hass, main_mi_type) except DeviceException as de: _LOGGER.warn(de) raise PlatformNotReady _LOGGER.info(f"{main_mi_type} is the main device of {host}.") hass.data[DOMAIN]['miot_main_entity'][host] = device hass.data[DOMAIN]['entities'][device.unique_id] = device async_add_devices([device], update_before_add=True) @asyncio.coroutine def async_service_handler(service): """Map services to methods on XiaomiMiioDevice.""" method = SERVICE_TO_METHOD.get(service.service) params = { key: value for key, value in service.data.items() if key != ATTR_ENTITY_ID } entity_ids = service.data.get(ATTR_ENTITY_ID) if entity_ids: devices = [ device for device in hass.data[DOMAIN]['entities'].values() if device.entity_id in entity_ids ] else: # devices = hass.data[DOMAIN]['entities'].values() _LOGGER.error("No entity_id specified.") update_tasks = [] for device in devices: yield from getattr(device, method["method"])(**params) update_tasks.append(device.async_update_ha_state(True)) if update_tasks: yield from asyncio.wait(update_tasks, loop=hass.loop) for service in SERVICE_TO_METHOD: schema = SERVICE_TO_METHOD[service].get("schema", SERVICE_SCHEMA) hass.services.async_register(DOMAIN, service, async_service_handler, schema=schema) else: _LOGGER.error("media player只能作为主设备!") pass
class MijiaCurtain(CoverEntity): def __init__(self, name, host, token, model): self._name = name self._current_position = 0 self._target_position = 0 self._action = 0 if model: self._model = model self._mapping = MIOT_MAPPING[model] else: self._mapping = { ATTR_MOTOR_CONTROL: {"siid": 0, "piid": 0}, ATTR_CURRENT_POSITION: {"siid": 0, "piid": 0}, ATTR_TARGET_POSITION: {"siid": 0, "piid": 0}, ATTR_PAUSE: 0, ATTR_OPEN: 0, ATTR_CLOSE: 0, } # init device self.miotDevice = MiotDevice(ip=host, token=token) _LOGGER.info("Init miot device: {}, {}".format(self._name, self.miotDevice)) # if model not config get model from miot device info if not model: self._model = self.miotDevice.info().model self._mapping = get_mapping(self._model, self._mapping) @property def supported_features(self): return SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_STOP | SUPPORT_SET_POSITION @property def name(self): return self._name @property def device_class(self) -> Optional[str]: return DEVICE_CLASS_CURTAIN @property def state(self): if self.is_opening: return STATE_OPENING if self.is_closing: return STATE_CLOSING closed = self.is_closed if closed is None: return None return STATE_CLOSED if closed else STATE_OPEN @property def state_attributes(self): data = { 'current_position': self._current_position, 'target_position': self._target_position, CONF_MODEL: self._model, } return data def update(self): self.update_current_position() self.update_target_position() self.update_action() _LOGGER.debug('update_state {} data: {}'.format(self._name, self.state_attributes)) def update_current_position(self): position = self.get_property(ATTR_CURRENT_POSITION) if position is None: return if 0 < position < 5: position = 0 if 95 < position < 100: position = 100 self._current_position = position def update_target_position(self): self._target_position = self.get_property(ATTR_TARGET_POSITION) def update_action(self): if ATTR_LUMI in self._model: self._action = self.get_property(ATTR_STATUS) else: self._action = self.get_property(ATTR_MOTOR_CONTROL) @property def is_opening(self): if ATTR_LUMI in self._model: return self._action == self._mapping[ATTR_OPENING] else: return self._action == self._mapping[ATTR_OPEN] @property def is_closing(self): if ATTR_LUMI in self._model: return self._action == self._mapping[ATTR_CLOSING] else: return self._action == self._mapping[ATTR_CLOSE] @property def is_closed(self): return self._current_position == 0 @property def is_opened(self): return self._current_position == 100 @property def current_cover_position(self): return self._current_position def open_cover(self, **kwargs) -> None: self.set_property(ATTR_MOTOR_CONTROL, self._mapping[ATTR_OPEN]) def close_cover(self, **kwargs): self.set_property(ATTR_MOTOR_CONTROL, self._mapping[ATTR_CLOSE]) def toggle(self, **kwargs) -> None: if self.is_closed: self.open_cover(**kwargs) else: self.close_cover(**kwargs) def stop_cover(self, **kwargs): self.set_property(ATTR_MOTOR_CONTROL, self._mapping[ATTR_PAUSE]) def set_cover_position(self, **kwargs): self.set_property(ATTR_TARGET_POSITION, kwargs['position']) def set_property(self, property_key, value): siid = self._mapping[property_key]['siid'] piid = self._mapping[property_key]['piid'] self.miotDevice.set_property_by(siid, piid, value) def get_property(self, property_key): value = None try: siid = self._mapping[property_key]['siid'] piid = self._mapping[property_key]['piid'] results = self.miotDevice.get_property_by(siid, piid) for result in results: if result["code"] == 0 and result["siid"] == siid and result['piid'] == piid: value = result["value"] except Exception: _LOGGER.error("Get property {} exception".format(property_key), exc_info=True) _LOGGER.debug("{}, {} is: {}".format(self._name, property_key, value)) return value
async def async_step_devinfo(self, user_input=None): errors = {} hint = "" if user_input is not None: self._devtype = user_input['devtype'] self._input2['devtype'] = self._devtype self._input2[CONF_MAPPING] = user_input[CONF_MAPPING] self._input2[CONF_CONTROL_PARAMS] = user_input[CONF_CONTROL_PARAMS] # self._input2['cloud_read'] = user_input['cloud_read'] self._input2['cloud_write'] = user_input.get('cloud_write') v = await validate_devinfo(self.hass, self._input2) if v == [[], []]: try: # print(result) if not user_input.get('cloud_read') and not user_input.get( 'cloud_write'): device = MiotDevice(ip=self._input2[CONF_HOST], token=self._input2[CONF_TOKEN], mapping=json.loads( self._input2[CONF_MAPPING])) result = device.get_properties_for_mapping() return self.async_create_entry( title=self._input2[CONF_NAME], data=self._input2, ) else: return self.async_show_form( step_id="cloudinfo", data_schema=vol.Schema({ vol.Required('did'): str, vol.Required('userId'): str, vol.Required('serviceToken'): str, vol.Required('ssecurity'): str, }), # description_placeholders={"device_info": hint}, errors=errors, ) except DeviceException as ex: errors["base"] = "no_local_access" hint = f"错误信息: {ex}" except Exception as exe: hint = f"错误信息: {exe}" else: errors["base"] = "bad_params" hint = "" if v[0]: hint += "\nmapping 缺少必须配置的项目:" for item in v[0]: hint += (item + ', ') if v[1]: hint += "\nparams 缺少必须配置的项目:" for item in v[1]: hint += (item + ', ') # if info: return self.async_show_form( step_id="devinfo", data_schema=vol.Schema({ vol.Required('devtype', default=user_input['devtype']): vol.In(SUPPORTED_DOMAINS), vol.Required(CONF_MAPPING, default=user_input[CONF_MAPPING]): str, vol.Required(CONF_CONTROL_PARAMS, default=user_input[CONF_CONTROL_PARAMS]): str, vol.Optional('cloud_read'): bool, vol.Optional('cloud_write'): bool, }), description_placeholders={"device_info": hint}, errors=errors, )
#!/usr/bin/env python3 from miio.miot_device import MiotDevice device = MiotDevice( { 'power': {'siid': 2, 'piid': 1}, 'power2': {'siid': 5, 'piid': 10}, 'power3': {'siid': 2, 'piid': 3}, 'power4': {'siid': 2, 'piid': 4}, 'power5': {'siid': 2, 'piid': 5}, 'power6': {'siid': 2, 'piid': 6}, 'power7': {'siid': 2, 'piid': 7}, 'power8': {'siid': 2, 'piid': 8}, 'power9': {'siid': 2, 'piid': 10}, 'powerA': {'siid': 2, 'piid': 11}, 'powerB': {'siid': 5, 'piid': 2}, 'powerC': {'siid': 6, 'piid': 1}, 'powerD': {'siid': 5, 'piid': 4}, 'powerE': {'siid': 5, 'piid': 5}, }, '192.168.1.28', '6dd1ec1c895a61d1b994b4a6242efe56') print('%s' % device.get_properties_for_mapping())
class DooyaCurtain(CoverEntity): def __init__(self, name, host, token, model): if model == BABAI_CURTAIN_BB82MJ or model == LUMI_CURTAIN_HAGL05: self._action_pause = 0 self._action_open = 1 self._action_close = 2 if model == SYNIOT_CURTAIN_SYC1: self._action_open = 0 self._action_close = 1 self._action_pause = 2 else: self._action_pause = 1 self._action_open = 2 self._action_close = 0 self._model = model self._name = name self._current_position = 0 self._target_position = 0 self._action = 0 self.miotDevice = MiotDevice(ip=host, token=token, mapping=MIOT_MAPPING[self._model]) _LOGGER.info("Init miot device: {}, {}".format(self._name, self.miotDevice)) @property def supported_features(self): return SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_STOP | SUPPORT_SET_POSITION @property def name(self): return self._name @property def device_class(self) -> Optional[str]: return DEVICE_CLASS_CURTAIN @property def state(self): if self.is_opening: return STATE_OPENING if self.is_closing: return STATE_CLOSING closed = self.is_closed if closed is None: return None return STATE_CLOSED if closed else STATE_OPEN @property def state_attributes(self): data = { 'current_position': self._current_position, 'target_position': self._target_position, 'action': self._action, } return data def update(self): self.update_current_position() self.update_target_position() self.update_action() _LOGGER.debug('update_state {} data: {}'.format( self._name, self.state_attributes)) def update_current_position(self): position = self.get_property('current_position') if position is None: return if position: if 95 < position < 100: position = 100 if 0 < position < 5: position = 0 self._current_position = position def update_target_position(self): self._target_position = self.get_property('target_position') def update_action(self): self._action = self.get_property('motor_control') @property def is_opening(self): self.update_action() return self._action == self._action_open @property def is_closing(self): self.update_action() return self._action == self._action_close @property def is_closed(self): self.update_current_position() return self._current_position == 0 @property def is_opened(self): self.update_current_position() return self._current_position == 100 @property def current_cover_position(self): self.update_current_position() return self._current_position def open_cover(self, **kwargs) -> None: self.miotDevice.set_property("motor_control", self._action_open) def close_cover(self, **kwargs): self.miotDevice.set_property("motor_control", self._action_close) def toggle(self, **kwargs) -> None: if self.is_closed: self.open_cover(**kwargs) else: self.close_cover(**kwargs) def stop_cover(self, **kwargs): self.miotDevice.set_property("motor_control", self._action_pause) def set_cover_position(self, **kwargs): self.miotDevice.set_property("target_position", kwargs['position']) def get_property(self, property_key): properties = [{ "did": property_key, **MIOT_MAPPING[self._model][property_key] }] value = None try: results = self.miotDevice.get_properties( properties, property_getter="get_properties", max_properties=15) for prop in results: if prop["code"] == 0 and prop["did"] == property_key: value = prop["value"] except Exception: _LOGGER.error("Get property {} exception".format(property_key), exc_info=True) _LOGGER.debug("{}, {} is: {}".format(self._name, property_key, value)) return value
async def async_step_devinfo(self, user_input=None): errors = {} hint = "" if user_input is not None: self._devtype = user_input['devtype'] self._input2['devtype'] = self._devtype self._input2[CONF_MAPPING] = user_input[CONF_MAPPING] self._input2[CONF_CONTROL_PARAMS] = user_input[CONF_CONTROL_PARAMS] self._input2['cloud_write'] = user_input.get('cloud_write') try: # print(result) if not user_input.get('cloud_read') and not user_input.get( 'cloud_write'): device = MiotDevice( ip=self._input2[CONF_HOST], token=self._input2[CONF_TOKEN], mapping=list( json.loads( self._input2[CONF_MAPPING]).values())[0]) result = device.get_properties_for_mapping() return self.async_create_entry( title=self._input2[CONF_NAME], data=self._input2, ) else: for item in self.hass.data[DOMAIN]['cloud_instance_list']: if item['username']: cloud = item['cloud_instance'] if cloud: if not self._did: for dev in self.hass.data[DOMAIN][ 'micloud_devices']: if dev.get( 'localip') == self._input2[CONF_HOST]: self._did = dev['did'] if self._did: self._input2['update_from_cloud'] = { 'did': self._did, 'userId': cloud.auth['user_id'], 'serviceToken': cloud.auth['service_token'], 'ssecurity': cloud.auth['ssecurity'], } if s := cloud.svr: self._input2['update_from_cloud'][ 'server_location'] = s if self._cloud_device: self._input2['cloud_device_info'] = { 'name': self._cloud_device.get('name'), 'mac': self._cloud_device.get('mac'), 'did': self._cloud_device.get('did'), 'model': self._cloud_device.get('model'), 'fw_version': self._cloud_device['extra'].get( 'fw_version'), } else: # 3rd party device and Manually added device doesn't have one self._input2['cloud_device_info'] = { 'name': self._input2[CONF_NAME], 'mac': "", 'did': self._did, 'model': self._input2[CONF_MODEL], 'fw_version': "", } return self.async_create_entry( title=self._input2[CONF_NAME], data=self._input2, ) else: return self.async_show_form( step_id="cloudinfo", data_schema=vol.Schema({ vol.Required('did'): str, vol.Required('userId', default=cloud.auth['user_id']): str, vol.Required('serviceToken', default=cloud.auth['service_token']): str, vol.Required('ssecurity', default=cloud.auth['ssecurity']): str, }), description_placeholders={ "device_info": "没找到 did,请手动填一下" }, errors=errors, ) else: return self.async_show_form( step_id="cloudinfo", data_schema=vol.Schema({ vol.Required('did'): str, vol.Required('userId'): str, vol.Required('serviceToken'): str, vol.Required('ssecurity'): str, }), # description_placeholders={"device_info": hint}, errors=errors, )