feat: improve config flow devices filter

This commit is contained in:
topsworld 2024-12-23 15:07:24 +08:00
parent 5d9a00d0b7
commit 13d76b66de
23 changed files with 164 additions and 100 deletions

View File

@ -50,7 +50,7 @@ import hashlib
import json import json
import secrets import secrets
import traceback import traceback
from typing import Optional from typing import Optional, Set
from aiohttp import web from aiohttp import web
from aiohttp.hdrs import METH_GET from aiohttp.hdrs import METH_GET
import voluptuous as vol import voluptuous as vol
@ -116,9 +116,10 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
_area_name_rule: Optional[str] _area_name_rule: Optional[str]
_action_debug: bool _action_debug: bool
_hide_non_standard_entities: bool _hide_non_standard_entities: bool
_display_devices_changed_notify: bool
_auth_info: Optional[dict] _auth_info: Optional[dict]
_nick_name: Optional[str] _nick_name: Optional[str]
_home_selected: Optional[dict] _home_selected: dict
_home_info_buffer: Optional[dict[str, str | dict[str, dict]]] _home_info_buffer: Optional[dict[str, str | dict[str, dict]]]
_home_list: Optional[dict] _home_list: Optional[dict]
_device_list_sorted: dict _device_list_sorted: dict
@ -152,6 +153,7 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
self._area_name_rule = None self._area_name_rule = None
self._action_debug = False self._action_debug = False
self._hide_non_standard_entities = False self._hide_non_standard_entities = False
self._display_devices_changed_notify = True
self._auth_info = None self._auth_info = None
self._nick_name = None self._nick_name = None
self._home_selected = {} self._home_selected = {}
@ -365,13 +367,6 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
except (MIoTOauthError, json.JSONDecodeError): except (MIoTOauthError, json.JSONDecodeError):
self._nick_name = DEFAULT_NICK_NAME self._nick_name = DEFAULT_NICK_NAME
_LOGGER.error('get nick name failed') _LOGGER.error('get nick name failed')
# Save auth_info
if not (await self._miot_storage.update_user_config_async(
uid=self._uid, cloud_server=self._cloud_server, config={
'auth_info': self._auth_info
})):
raise MIoTError(
'miot_storage.update_user_config_async error')
except Exception as err: except Exception as err:
_LOGGER.error( _LOGGER.error(
'get_access_token, %s, %s', err, traceback.format_exc()) 'get_access_token, %s, %s', err, traceback.format_exc())
@ -385,6 +380,12 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
self._uid = self._home_info_buffer['uid'] self._uid = self._home_info_buffer['uid']
if self._uid == self._nick_name: if self._uid == self._nick_name:
self._nick_name = DEFAULT_NICK_NAME self._nick_name = DEFAULT_NICK_NAME
# Save auth_info
if not (await self._miot_storage.update_user_config_async(
uid=self._uid, cloud_server=self._cloud_server, config={
'auth_info': self._auth_info
})):
raise MIoTError('miot_storage.update_user_config_async error')
except Exception as err: except Exception as err:
_LOGGER.error( _LOGGER.error(
'get_homeinfos error, %s, %s', err, traceback.format_exc()) 'get_homeinfos error, %s, %s', err, traceback.format_exc())
@ -495,11 +496,11 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
_LOGGER.debug('async_step_homes_select') _LOGGER.debug('async_step_homes_select')
try: try:
if user_input is None: if user_input is None:
return await self.display_homes_select_form('') return await self.__display_homes_select_form('')
home_selected: list = user_input.get('home_infos', []) home_selected: list = user_input.get('home_infos', [])
if not home_selected: if not home_selected:
return await self.display_homes_select_form( return await self.__display_homes_select_form(
'no_family_selected') 'no_family_selected')
for home_id, home_info in self._home_info_buffer[ for home_id, home_info in self._home_info_buffer[
'homes']['home_list'].items(): 'homes']['home_list'].items():
@ -512,7 +513,7 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
for did, dev_info in self._home_info_buffer['devices'].items() for did, dev_info in self._home_info_buffer['devices'].items()
if dev_info['home_id'] in home_selected} if dev_info['home_id'] in home_selected}
if not devices_list: if not devices_list:
return await self.display_homes_select_form('no_devices') return await self.__display_homes_select_form('no_devices')
self._device_list_sorted = dict(sorted( self._device_list_sorted = dict(sorted(
devices_list.items(), key=lambda item: devices_list.items(), key=lambda item:
item[1].get('home_id', '')+item[1].get('room_id', ''))) item[1].get('home_id', '')+item[1].get('room_id', '')))
@ -524,7 +525,7 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
_LOGGER.error( _LOGGER.error(
'save devices async failed, %s, %s', 'save devices async failed, %s, %s',
self._uid, self._cloud_server) self._uid, self._cloud_server)
return await self.display_homes_select_form( return await self.__display_homes_select_form(
'devices_storage_failed') 'devices_storage_failed')
if user_input.get('advanced_options', False): if user_input.get('advanced_options', False):
return await self.async_step_advanced_options() return await self.async_step_advanced_options()
@ -539,7 +540,7 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
'error': f'config_flow error, {err}'} 'error': f'config_flow error, {err}'}
) from err ) from err
async def display_homes_select_form(self, reason: str): async def __display_homes_select_form(self, reason: str):
return self.async_show_form( return self.async_show_form(
step_id='homes_select', step_id='homes_select',
data_schema=vol.Schema({ data_schema=vol.Schema({
@ -576,7 +577,9 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
vol.Required( vol.Required(
'hide_non_standard_entities', 'hide_non_standard_entities',
default=self._hide_non_standard_entities): bool, default=self._hide_non_standard_entities): bool,
vol.Required(
'display_devices_changed_notify',
default=self._display_devices_changed_notify): bool,
}), }),
last_step=False, last_step=False,
) )
@ -586,93 +589,68 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
): ):
if user_input: if user_input:
# Room filter # Room filter
include_items: dict = {}
exclude_items: dict = {}
room_list_in: list = user_input.get('room_list', []) room_list_in: list = user_input.get('room_list', [])
if room_list_in: if room_list_in:
room_filter_mode: str = user_input.get( if user_input.get(
'room_filter_mode', None) 'room_filter_mode', 'include') == 'include':
if room_filter_mode == 'exclude': include_items['room_id'] = room_list_in
self._device_list_filter = { else:
did: dev_info exclude_items['room_id'] = room_list_in
for did, dev_info in self._device_list_sorted.items() # Connect Type filter
if dev_info['room_id'] not in room_list_in}
elif room_filter_mode == 'include':
self._device_list_filter = {
did: dev_info
for did, dev_info in self._device_list_sorted.items()
if dev_info['room_id'] in room_list_in}
# Type filter
type_list_in: list = user_input.get('type_list', []) type_list_in: list = user_input.get('type_list', [])
if type_list_in: if type_list_in:
type_filter_mode: str = user_input.get( if user_input.get(
'type_filter_mode', None) 'type_filter_mode', 'include') == 'include':
if type_filter_mode == 'exclude': include_items['connect_type'] = type_list_in
self._device_list_filter = { else:
did: dev_info exclude_items['connect_type'] = type_list_in
for did, dev_info in self._device_list_sorted.items()
if dev_info['connect_type'] not in type_list_in}
elif type_filter_mode == 'include':
self._device_list_filter = {
did: dev_info
for did, dev_info in self._device_list_sorted.items()
if str(dev_info['connect_type']) in type_list_in}
# Model filter # Model filter
model_list_in: list = user_input.get('model_list', []) model_list_in: list = user_input.get('model_list', [])
if model_list_in: if model_list_in:
model_filter_mode: str = user_input.get( if user_input.get(
'model_filter_mode', None) 'model_filter_mode', 'include') == 'include':
if model_filter_mode == 'exclude': include_items['model'] = model_list_in
self._device_list_filter = { else:
did: dev_info exclude_items['model'] = model_list_in
for did, dev_info in self._device_list_sorted.items()
if dev_info['model'] not in model_list_in}
elif model_filter_mode == 'include':
self._device_list_filter = {
did: dev_info
for did, dev_info in self._device_list_sorted.items()
if dev_info['model'] in model_list_in}
# Device filter # Device filter
device_list_in: list = user_input.get('device_list', []) device_list_in: list = user_input.get('device_list', [])
if device_list_in: if device_list_in:
devices_filter_mode: str = user_input.get( if user_input.get(
'devices_filter_mode', None) 'devices_filter_mode', 'include') == 'include':
if devices_filter_mode == 'exclude': include_items['did'] = device_list_in
self._device_list_filter = {
did: dev_info
for did, dev_info in self._device_list_sorted.items()
if did not in device_list_in}
elif devices_filter_mode == 'include':
self._device_list_filter = {
did: dev_info
for did, dev_info in self._device_list_sorted.items()
if did in device_list_in}
else: else:
raise MIoTError('invalid devices_filter_mode') exclude_items['did'] = device_list_in
if self._device_list_filter: device_filter_list = self.__devices_filter(
devices=self._device_list_sorted,
logic_or=(user_input.get('statistics_logic', 'or') == 'or'),
item_in=include_items, item_ex=exclude_items)
if not device_filter_list:
raise AbortFlow( raise AbortFlow(
reason='config_flow_error', reason='config_flow_error',
description_placeholders={ description_placeholders={
'error': 'invalid devices_filter'}) 'error': 'invalid devices_filter'})
self._device_list_sorted = dict(sorted( self._device_list_sorted = dict(sorted(
self._device_list_filter.items(), key=lambda item: device_filter_list.items(), key=lambda item:
item[1].get('home_id', '')+item[1].get('room_id', ''))) item[1].get('home_id', '')+item[1].get('room_id', '')))
# Save devices # Save devices
if not await self._miot_storage.save_async( if not await self._miot_storage.save_async(
domain='miot_devices', domain='miot_devices',
name=f'{self._uid}_{self._cloud_server}', name=f'{self._uid}_{self._cloud_server}',
data=self._device_list_sorted): data=self._device_list_sorted):
_LOGGER.error( return await self.__display_devices_filter_form(
'save devices async failed, %s, %s', reason='no_devices_selected')
self._uid, self._cloud_server)
raise AbortFlow(
reason='config_flow_error',
description_placeholders={
'error': 'save devices failed'})
return await self.config_flow_done() return await self.config_flow_done()
return await self.__display_devices_filter_form(reason='')
async def __display_devices_filter_form(self, reason: str):
tip_devices: str = self._miot_i18n.translate( tip_devices: str = self._miot_i18n.translate(
key='config.other.devices') key='config.other.devices')
tip_without_room: str = self._miot_i18n.translate( tip_without_room: str = self._miot_i18n.translate(
key='config.other.without_room') key='config.other.without_room')
trans_statistics_logic: dict = self._miot_i18n.translate(
key='config.statistics_logic')
trans_filter_mode: dict = self._miot_i18n.translate( trans_filter_mode: dict = self._miot_i18n.translate(
key='config.filter_mode') key='config.filter_mode')
trans_connect_type: dict = self._miot_i18n.translate( trans_connect_type: dict = self._miot_i18n.translate(
@ -684,24 +662,21 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
device_list: dict = {} device_list: dict = {}
for did, info in self._device_list_sorted.items(): for did, info in self._device_list_sorted.items():
device_list[did] = ( device_list[did] = (
f'{info["home_name"]} {info["room_name"]} - ' + f'[ {info["home_name"]} {info["room_name"]} ] ' +
f'{info["name"]} - {did}') f'{info["name"]}, {did}')
room_device_count.setdefault(info['room_id'], 0) room_device_count.setdefault(info['room_id'], 0)
room_device_count[info['room_id']] += 1 room_device_count[info['room_id']] += 1
model_device_count.setdefault(info['model'], 0) model_device_count.setdefault(info['model'], 0)
model_device_count[info['model']] += 1 model_device_count[info['model']] += 1
connect_type_count.setdefault(str(info['connect_type']), 0) connect_type_count.setdefault(str(info['connect_type']), 0)
connect_type_count[str(info['connect_type'])] += 1 connect_type_count[str(info['connect_type'])] += 1
model_list: dict = {} model_list: dict = {}
for model, count in model_device_count.items(): for model, count in model_device_count.items():
model_list[model] = f'{model} [ {count} {tip_devices} ]' model_list[model] = f'{model} [ {count} {tip_devices} ]'
type_list: dict = { type_list: dict = {
k: f'{trans_connect_type.get(k, f"Connect Type ({k})")} ' k: f'{trans_connect_type.get(k, f"Connect Type ({k})")} '
f'[ {v} {tip_devices} ]' f'[ {v} {tip_devices} ]'
for k, v in connect_type_count.items()} for k, v in connect_type_count.items()}
room_list: dict = {} room_list: dict = {}
for home_id, home_info in self._home_selected.items(): for home_id, home_info in self._home_selected.items():
for room_id, room_name in home_info['room_info'].items(): for room_id, room_name in home_info['room_info'].items():
@ -714,7 +689,6 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
room_list[home_id] = ( room_list[home_id] = (
f'{home_info["home_name"]} {tip_without_room}' f'{home_info["home_name"]} {tip_without_room}'
f' [ {room_device_count[home_id]}{tip_devices} ]') f' [ {room_device_count[home_id]}{tip_devices} ]')
return self.async_show_form( return self.async_show_form(
step_id='devices_filter', step_id='devices_filter',
data_schema=vol.Schema({ data_schema=vol.Schema({
@ -731,11 +705,47 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
vol.Required('devices_filter_mode', default='exclude'): vol.Required('devices_filter_mode', default='exclude'):
vol.In(trans_filter_mode), vol.In(trans_filter_mode),
vol.Optional('device_list'): cv.multi_select(dict(sorted( vol.Optional('device_list'): cv.multi_select(dict(sorted(
device_list.items(), key=lambda device: device[1]))) device_list.items(), key=lambda device: device[1]))),
vol.Required('statistics_logic', default='or'):
vol.In(trans_statistics_logic),
}), }),
errors={'base': reason},
last_step=False last_step=False
) )
def __devices_filter(
self, devices: dict, logic_or: bool, item_in: dict, item_ex: dict
) -> dict:
include_set: Set = set([])
if not item_in:
include_set = set(devices.keys())
else:
filter_item: list[set] = []
for key, value in item_in.items():
filter_item.append(set([
did for did, info in devices.items()
if str(info[key]) in value]))
include_set = (
set.union(*filter_item)
if logic_or else set.intersection(*filter_item))
if not include_set:
return {}
if item_ex:
filter_item: list[set] = []
for key, value in item_ex.items():
filter_item.append(set([
did for did, info in devices.items()
if str(info[key]) in value]))
exclude_set: Set = (
set.union(*filter_item)
if logic_or else set.intersection(*filter_item))
if exclude_set:
include_set = include_set-exclude_set
if not include_set:
return {}
return {
did: info for did, info in devices.items() if did in include_set}
async def config_flow_done(self): async def config_flow_done(self):
return self.async_create_entry( return self.async_create_entry(
title=( title=(
@ -756,10 +766,12 @@ class XiaomiMihomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
'action_debug': self._action_debug, 'action_debug': self._action_debug,
'hide_non_standard_entities': 'hide_non_standard_entities':
self._hide_non_standard_entities, self._hide_non_standard_entities,
'display_devices_changed_notify':
self._display_devices_changed_notify
}) })
@staticmethod @ staticmethod
@callback @ callback
def async_get_options_flow( def async_get_options_flow(
config_entry: config_entries.ConfigEntry, config_entry: config_entries.ConfigEntry,
) -> config_entries.OptionsFlow: ) -> config_entries.OptionsFlow:
@ -1206,11 +1218,11 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
if home_id in home_list] if home_id in home_list]
self._home_list = dict(sorted(home_list.items())) self._home_list = dict(sorted(home_list.items()))
return await self.display_homes_select_form('') return await self.__display_homes_select_form('')
self._home_selected_list = user_input.get('home_infos', []) self._home_selected_list = user_input.get('home_infos', [])
if not self._home_selected_list: if not self._home_selected_list:
return await self.display_homes_select_form('no_family_selected') return await self.__display_homes_select_form('no_family_selected')
self._ctrl_mode = user_input.get('ctrl_mode') self._ctrl_mode = user_input.get('ctrl_mode')
self._home_selected_dict = {} self._home_selected_dict = {}
for home_id, home_info in self._home_info_buffer[ for home_id, home_info in self._home_info_buffer[
@ -1223,7 +1235,7 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
for did, dev_info in self._home_info_buffer['devices'].items() for did, dev_info in self._home_info_buffer['devices'].items()
if dev_info['home_id'] in self._home_selected_list} if dev_info['home_id'] in self._home_selected_list}
if not self._device_list: if not self._device_list:
return await self.display_homes_select_form('no_devices') return await self.__display_homes_select_form('no_devices')
# Statistics devices changed # Statistics devices changed
self._devices_add = [] self._devices_add = []
self._devices_remove = [] self._devices_remove = []
@ -1241,17 +1253,14 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
self._devices_add, self._devices_remove) self._devices_add, self._devices_remove)
return await self.async_step_update_trans_rules() return await self.async_step_update_trans_rules()
async def display_homes_select_form(self, reason: str): async def __display_homes_select_form(self, reason: str):
return self.async_show_form( return self.async_show_form(
step_id='homes_select', step_id='homes_select',
data_schema=vol.Schema({ data_schema=vol.Schema({
vol.Required( vol.Required('home_infos', default=self._home_selected_list):
'ctrl_mode', default=self._ctrl_mode cv.multi_select(self._home_list),
): vol.In(self._miot_i18n.translate(key='config.control_mode')), vol.Required('ctrl_mode', default=self._ctrl_mode): vol.In(
vol.Required( self._miot_i18n.translate(key='config.control_mode')),
'home_infos',
default=self._home_selected_list
): cv.multi_select(self._home_list),
}), }),
errors={'base': reason}, errors={'base': reason},
description_placeholders={ description_placeholders={

View File

@ -9,6 +9,10 @@
"auto": "automatisch", "auto": "automatisch",
"cloud": "Cloud" "cloud": "Cloud"
}, },
"statistics_logic": {
"or": "ODER-Logik",
"and": "UND-Logik"
},
"filter_mode": { "filter_mode": {
"exclude": "ausschließen", "exclude": "ausschließen",
"include": "einschließen" "include": "einschließen"

View File

@ -9,6 +9,10 @@
"auto": "Auto", "auto": "Auto",
"cloud": "Cloud" "cloud": "Cloud"
}, },
"statistics_logic": {
"or": "OR logic",
"and": "AND logic"
},
"filter_mode": { "filter_mode": {
"exclude": "Exclude", "exclude": "Exclude",
"include": "Include" "include": "Include"

View File

@ -9,6 +9,10 @@
"auto": "automático", "auto": "automático",
"cloud": "nube" "cloud": "nube"
}, },
"statistics_logic": {
"or": "lógica OR",
"and": "lógica AND"
},
"filter_mode": { "filter_mode": {
"exclude": "excluir", "exclude": "excluir",
"include": "incluir" "include": "incluir"

View File

@ -9,6 +9,10 @@
"auto": "automatique", "auto": "automatique",
"cloud": "cloud" "cloud": "cloud"
}, },
"statistics_logic": {
"or": "ou logique",
"and": "et logique"
},
"filter_mode": { "filter_mode": {
"exclude": "exclure", "exclude": "exclure",
"include": "inclure" "include": "inclure"

View File

@ -9,6 +9,10 @@
"auto": "自動", "auto": "自動",
"cloud": "クラウド" "cloud": "クラウド"
}, },
"statistics_logic": {
"or": "ORロジック",
"and": "ANDロジック"
},
"filter_mode": { "filter_mode": {
"exclude": "除外", "exclude": "除外",
"include": "含む" "include": "含む"

View File

@ -9,6 +9,10 @@
"auto": "Automatisch", "auto": "Automatisch",
"cloud": "Cloud" "cloud": "Cloud"
}, },
"statistics_logic": {
"or": "OF-logica",
"and": "EN-logica"
},
"filter_mode": { "filter_mode": {
"exclude": "Uitsluiten", "exclude": "Uitsluiten",
"include": "Inclusief" "include": "Inclusief"

View File

@ -9,6 +9,10 @@
"auto": "automático", "auto": "automático",
"cloud": "nuvem" "cloud": "nuvem"
}, },
"statistics_logic": {
"or": "lógica OU",
"and": "lógica E"
},
"filter_mode": { "filter_mode": {
"exclude": "excluir", "exclude": "excluir",
"include": "incluir" "include": "incluir"

View File

@ -9,6 +9,10 @@
"auto": "Automático", "auto": "Automático",
"cloud": "Nuvem" "cloud": "Nuvem"
}, },
"statistics_logic": {
"or": "Ou lógica",
"and": "E lógica"
},
"filter_mode": { "filter_mode": {
"exclude": "Excluir", "exclude": "Excluir",
"include": "Incluir" "include": "Incluir"

View File

@ -9,6 +9,10 @@
"auto": "автоматический", "auto": "автоматический",
"cloud": "облако" "cloud": "облако"
}, },
"statistics_logic": {
"or": "логика ИЛИ",
"and": "логика И"
},
"filter_mode": { "filter_mode": {
"exclude": "исключить", "exclude": "исключить",
"include": "включить" "include": "включить"

View File

@ -15,6 +15,10 @@
"room": "房间名 (卧室)", "room": "房间名 (卧室)",
"home": "家庭名 (米家)" "home": "家庭名 (米家)"
}, },
"statistics_logic": {
"or": "或逻辑",
"and": "与逻辑"
},
"filter_mode": { "filter_mode": {
"exclude": "排除", "exclude": "排除",
"include": "包含" "include": "包含"

View File

@ -9,6 +9,10 @@
"auto": "自動", "auto": "自動",
"cloud": "雲端" "cloud": "雲端"
}, },
"statistics_logic": {
"or": "或邏輯",
"and": "與邏輯"
},
"filter_mode": { "filter_mode": {
"exclude": "排除", "exclude": "排除",
"include": "包含" "include": "包含"

View File

@ -45,6 +45,7 @@
"title": "Geräte filtern", "title": "Geräte filtern",
"description": "## Gebrauchsanweisung\r\n- Unterstützt das Filtern von Geräten nach Raumnamen und Gerätetypen sowie das Filtern nach Gerätedimensionen.\r\n- Sie können auch die entsprechende Integrationsoption \"Konfiguration> Geräteliste aktualisieren\" aufrufen, um die Filterung erneut durchzuführen.", "description": "## Gebrauchsanweisung\r\n- Unterstützt das Filtern von Geräten nach Raumnamen und Gerätetypen sowie das Filtern nach Gerätedimensionen.\r\n- Sie können auch die entsprechende Integrationsoption \"Konfiguration> Geräteliste aktualisieren\" aufrufen, um die Filterung erneut durchzuführen.",
"data": { "data": {
"statistics_logic": "Statistiklogik",
"room_filter_mode": "Familienraum filtern", "room_filter_mode": "Familienraum filtern",
"room_list": "Familienraum", "room_list": "Familienraum",
"type_filter_mode": "Gerätetyp filtern", "type_filter_mode": "Gerätetyp filtern",

View File

@ -45,6 +45,7 @@
"title": "Filter Devices", "title": "Filter Devices",
"description": "## Introduction\r\n- Supports filtering devices by room name and device type, and also supports device dimension filtering.\r\n- You can also re-filter on the corresponding integration page [Configuration>Update Device List].", "description": "## Introduction\r\n- Supports filtering devices by room name and device type, and also supports device dimension filtering.\r\n- You can also re-filter on the corresponding integration page [Configuration>Update Device List].",
"data": { "data": {
"statistics_logic": "Statistics Logic",
"room_filter_mode": "Filter Family Rooms", "room_filter_mode": "Filter Family Rooms",
"room_list": "Family Rooms", "room_list": "Family Rooms",
"type_filter_mode": "Filter Device Connect Type", "type_filter_mode": "Filter Device Connect Type",

View File

@ -45,6 +45,7 @@
"title": "Filtrar Dispositivos", "title": "Filtrar Dispositivos",
"description": "## Introducción\r\n- Admite la filtración de dispositivos por nombre de habitación y tipo de dispositivo, y también admite la filtración por familia.\r\n- También puede volver a filtrar en la página correspondiente de la integración [Configuración>Actualizar lista de dispositivos].", "description": "## Introducción\r\n- Admite la filtración de dispositivos por nombre de habitación y tipo de dispositivo, y también admite la filtración por familia.\r\n- También puede volver a filtrar en la página correspondiente de la integración [Configuración>Actualizar lista de dispositivos].",
"data": { "data": {
"statistics_logic": "Lógica de Estadísticas",
"room_filter_mode": "Filtrar Habitaciones de la Familia", "room_filter_mode": "Filtrar Habitaciones de la Familia",
"room_list": "Habitaciones de la Familia", "room_list": "Habitaciones de la Familia",
"type_filter_mode": "Filtrar Tipo de Dispositivo", "type_filter_mode": "Filtrar Tipo de Dispositivo",

View File

@ -33,7 +33,7 @@
}, },
"advanced_options": { "advanced_options": {
"title": "Paramètres Avancés", "title": "Paramètres Avancés",
"description": "## Introduction\r\n### Sauf si vous comprenez très bien la signification des options suivantes, veuillez les laisser par défaut.\r\n###Filtrer les appareils\r\nPrend en charge le filtrage des appareils en fonction du nom de la pièce et du type d'appareil, ainsi que le filtrage basé sur les appareils.\r\n### Mode de Contrôle\r\n- Automatique : Lorsqu'une passerelle Xiaomi est disponible dans le réseau local, Home Assistant enverra les commandes de contrôle des appareils via la passerelle pour permettre le contrôle local. Si aucune passerelle n'est disponible dans le réseau local, Home Assistant essaiera d'envoyer les commandes de contrôle des appareils via le protocole OT Xiaomi pour permettre le contrôle local. Seules si les conditions de contrôle local ci-dessus ne sont pas remplies, les commandes de contrôle des appareils seront envoyées via le cloud.\r\n- Cloud : Les commandes de contrôle des appareils sont envoyées uniquement via le cloud.\r\n### Mode de Débogage dActions\r\nPour les méthodes définies par les appareils MIoT-Spec-V2, en plus de générer une entité de notification, une entité de champ de texte sera également générée pour vous permettre d'envoyer des commandes de contrôle aux appareils lors du débogage.\r\n### Masquer les Entités Non Standard\r\nMasquer les entités générées par des instances MIoT-Spec-V2 non standard et commençant par \"*\".", "description": "## Introduction\r\n### Sauf si vous comprenez très bien la signification des options suivantes, veuillez les laisser par défaut.\r\n### Filtrer les appareils\r\nPrend en charge le filtrage des appareils en fonction du nom de la pièce et du type d'appareil, ainsi que le filtrage basé sur les appareils.\r\n### Mode de Contrôle\r\n- Automatique : Lorsqu'une passerelle Xiaomi est disponible dans le réseau local, Home Assistant enverra les commandes de contrôle des appareils via la passerelle pour permettre le contrôle local. Si aucune passerelle n'est disponible dans le réseau local, Home Assistant essaiera d'envoyer les commandes de contrôle des appareils via le protocole OT Xiaomi pour permettre le contrôle local. Seules si les conditions de contrôle local ci-dessus ne sont pas remplies, les commandes de contrôle des appareils seront envoyées via le cloud.\r\n- Cloud : Les commandes de contrôle des appareils sont envoyées uniquement via le cloud.\r\n### Mode de Débogage dActions\r\nPour les méthodes définies par les appareils MIoT-Spec-V2, en plus de générer une entité de notification, une entité de champ de texte sera également générée pour vous permettre d'envoyer des commandes de contrôle aux appareils lors du débogage.\r\n### Masquer les Entités Non Standard\r\nMasquer les entités générées par des instances MIoT-Spec-V2 non standard et commençant par \"*\".",
"data": { "data": {
"devices_filter": "Filtrer les Appareils", "devices_filter": "Filtrer les Appareils",
"ctrl_mode": "Mode de Contrôle", "ctrl_mode": "Mode de Contrôle",
@ -45,6 +45,7 @@
"title": "Filtrer les Appareils", "title": "Filtrer les Appareils",
"description": "## Introduction\r\n- Prend en charge le filtrage des appareils en fonction du nom de la pièce et du type d'appareil, ainsi que le filtrage basé sur les appareils.\r\n- Vous pouvez également accéder à la page de filtrage correspondante de l'intégration [Configuration> Mettre à jour la liste des appareils] pour refiltrer.", "description": "## Introduction\r\n- Prend en charge le filtrage des appareils en fonction du nom de la pièce et du type d'appareil, ainsi que le filtrage basé sur les appareils.\r\n- Vous pouvez également accéder à la page de filtrage correspondante de l'intégration [Configuration> Mettre à jour la liste des appareils] pour refiltrer.",
"data": { "data": {
"statistics_logic": "Logique de Statistiques",
"room_filter_mode": "Filtrer les Pièces", "room_filter_mode": "Filtrer les Pièces",
"room_list": "Pièces", "room_list": "Pièces",
"type_filter_mode": "Filtrer les Types d'Appareils", "type_filter_mode": "Filtrer les Types d'Appareils",

View File

@ -33,7 +33,7 @@
}, },
"advanced_options": { "advanced_options": {
"title": "高度な設定オプション", "title": "高度な設定オプション",
"description": "## 紹介\r\n### 以下のオプションの意味がよくわからない場合は、デフォルトのままにしてください。\r\n###デバイスのフィルタリング\r\n部屋名とデバイスタイプでデバイスをフィルタリングすることができます。デバイスの次元でフィルタリングすることもできます。\r\n### コントロールモード\r\n- 自動ローカルネットワーク内に利用可能なXiaomi中央ゲートウェイがある場合、Home Assistantはデバイス制御命令を送信するために優先的に中央ゲートウェイを使用します。ローカルネットワークに中央ゲートウェイがない場合、Xiaomi OTプロトコルを使用してデバイス制御命令を送信し、ローカル制御機能を実現します。上記のローカル制御条件が満たされない場合のみ、デバイス制御命令はクラウドを介して送信されます。\r\n- クラウド:制御命令はクラウドを介してのみ送信されます。\r\n### Actionデバッグモード\r\nデバイスが定義するMIoT-Spec-V2のメソッドに対して、通知エンティティを生成するだけでなく、デバイスに制御命令を送信するためのテキスト入力ボックスエンティティも生成されます。デバッグ時にデバイスに制御命令を送信するために使用できます。\r\n### 非標準生成エンティティを隠す\r\n「*」で始まる名前の非標準MIoT-Spec-V2インスタンスによって生成されたエンティティを非表示にします。", "description": "## 紹介\r\n### 以下のオプションの意味がよくわからない場合は、デフォルトのままにしてください。\r\n### デバイスのフィルタリング\r\n部屋名とデバイスタイプでデバイスをフィルタリングすることができます。デバイスの次元でフィルタリングすることもできます。\r\n### コントロールモード\r\n- 自動ローカルネットワーク内に利用可能なXiaomi中央ゲートウェイがある場合、Home Assistantはデバイス制御命令を送信するために優先的に中央ゲートウェイを使用します。ローカルネットワークに中央ゲートウェイがない場合、Xiaomi OTプロトコルを使用してデバイス制御命令を送信し、ローカル制御機能を実現します。上記のローカル制御条件が満たされない場合のみ、デバイス制御命令はクラウドを介して送信されます。\r\n- クラウド:制御命令はクラウドを介してのみ送信されます。\r\n### Actionデバッグモード\r\nデバイスが定義するMIoT-Spec-V2のメソッドに対して、通知エンティティを生成するだけでなく、デバイスに制御命令を送信するためのテキスト入力ボックスエンティティも生成されます。デバッグ時にデバイスに制御命令を送信するために使用できます。\r\n### 非標準生成エンティティを隠す\r\n「*」で始まる名前の非標準MIoT-Spec-V2インスタンスによって生成されたエンティティを非表示にします。",
"data": { "data": {
"devices_filter": "デバイスをフィルタリング", "devices_filter": "デバイスをフィルタリング",
"ctrl_mode": "コントロールモード", "ctrl_mode": "コントロールモード",
@ -45,6 +45,7 @@
"title": "デバイスをフィルタリング", "title": "デバイスをフィルタリング",
"description": "## 紹介\r\n- 部屋名とデバイスタイプでデバイスをフィルタリングすることができます。デバイスの次元でフィルタリングすることもできます。\r\n- 対応する統合項目【設定>デバイスリストの更新】ページに移動して再度フィルタリングすることもできます。", "description": "## 紹介\r\n- 部屋名とデバイスタイプでデバイスをフィルタリングすることができます。デバイスの次元でフィルタリングすることもできます。\r\n- 対応する統合項目【設定>デバイスリストの更新】ページに移動して再度フィルタリングすることもできます。",
"data": { "data": {
"statistics_logic": "統計ロジック",
"room_filter_mode": "家族の部屋をフィルタリング", "room_filter_mode": "家族の部屋をフィルタリング",
"room_list": "家族の部屋", "room_list": "家族の部屋",
"type_filter_mode": "デバイスタイプをフィルタリング", "type_filter_mode": "デバイスタイプをフィルタリング",

View File

@ -45,6 +45,7 @@
"title": "Apparaten filteren", "title": "Apparaten filteren",
"description": "## Inleiding\r\n- Ondersteunt het filteren van apparaten op basis van kamer- en apparaattypen, en ondersteunt ook apparaatdimensiefiltering.\r\n- U kunt ook naar de overeenkomstige integratie-item [Configuratie>Apparaatlijst bijwerken] pagina gaan om opnieuw te filteren.", "description": "## Inleiding\r\n- Ondersteunt het filteren van apparaten op basis van kamer- en apparaattypen, en ondersteunt ook apparaatdimensiefiltering.\r\n- U kunt ook naar de overeenkomstige integratie-item [Configuratie>Apparaatlijst bijwerken] pagina gaan om opnieuw te filteren.",
"data": { "data": {
"statistics_logic": "Statistische logica",
"room_filter_mode": "Kamerfiltermodus", "room_filter_mode": "Kamerfiltermodus",
"room_list": "Kamers", "room_list": "Kamers",
"type_filter_mode": "Apparaattypen filteren", "type_filter_mode": "Apparaattypen filteren",

View File

@ -45,6 +45,7 @@
"title": "Filtrar Dispositivos", "title": "Filtrar Dispositivos",
"description": "## Introdução\r\n- Suporte para filtrar dispositivos por nome da sala e tipo de dispositivo, bem como filtragem por família.\r\n- Você também pode acessar a página correspondente da integração [Configuração>Atualizar Lista de Dispositivos] para refiltrar.", "description": "## Introdução\r\n- Suporte para filtrar dispositivos por nome da sala e tipo de dispositivo, bem como filtragem por família.\r\n- Você também pode acessar a página correspondente da integração [Configuração>Atualizar Lista de Dispositivos] para refiltrar.",
"data": { "data": {
"statistics_logic": "Lógica de Estatísticas",
"room_filter_mode": "Filtrar por Sala", "room_filter_mode": "Filtrar por Sala",
"room_list": "Salas", "room_list": "Salas",
"type_filter_mode": "Filtrar por Tipo de Dispositivo", "type_filter_mode": "Filtrar por Tipo de Dispositivo",

View File

@ -45,6 +45,7 @@
"title": "Filtrar Dispositivos", "title": "Filtrar Dispositivos",
"description": "## Introdução\r\n- Suporta a filtragem de dispositivos por nome de sala e tipo de dispositivo, bem como a filtragem por família.\r\n- Pode também aceder à página de configuração correspondente da integração [Configuração > Atualizar Lista de Dispositivos] para refazer a filtragem.", "description": "## Introdução\r\n- Suporta a filtragem de dispositivos por nome de sala e tipo de dispositivo, bem como a filtragem por família.\r\n- Pode também aceder à página de configuração correspondente da integração [Configuração > Atualizar Lista de Dispositivos] para refazer a filtragem.",
"data": { "data": {
"statistics_logic": "Lógica de Estatísticas",
"room_filter_mode": "Filtrar por Sala", "room_filter_mode": "Filtrar por Sala",
"room_list": "Salas", "room_list": "Salas",
"type_filter_mode": "Filtrar por Tipo de Dispositivo", "type_filter_mode": "Filtrar por Tipo de Dispositivo",

View File

@ -45,6 +45,7 @@
"title": "Фильтрация устройств", "title": "Фильтрация устройств",
"description": "## Введение\r\n- Поддерживает фильтрацию устройств по названию комнаты и типу устройства, а также фильтрацию по уровню устройства.\r\n- Вы также можете перейти на соответствующую страницу интеграции [Настройки> Обновить список устройств], чтобы перефильтровать.", "description": "## Введение\r\n- Поддерживает фильтрацию устройств по названию комнаты и типу устройства, а также фильтрацию по уровню устройства.\r\n- Вы также можете перейти на соответствующую страницу интеграции [Настройки> Обновить список устройств], чтобы перефильтровать.",
"data": { "data": {
"statistics_logic": "Логика статистики",
"room_filter_mode": "Фильтрация по комнатам семьи", "room_filter_mode": "Фильтрация по комнатам семьи",
"room_list": "Комнаты семьи", "room_list": "Комнаты семьи",
"type_filter_mode": "Фильтрация по типу устройства", "type_filter_mode": "Фильтрация по типу устройства",

View File

@ -33,7 +33,7 @@
}, },
"advanced_options": { "advanced_options": {
"title": "高级设置选项", "title": "高级设置选项",
"description": "## 使用介绍\r\n### 除非您非常清楚下列选项的含义,否则请保持默认。\r\n###筛选设备\r\n支持按照房间名称和设备类型筛选设备同时也支持设备维度筛选。\r\n### 控制模式\r\n- 自动:本地局域网内存在可用的小米中枢网关时, Home Assistant 会优先通过中枢网关发送设备控制指令以实现本地化控制功能。本地局域网不存在中枢时会尝试通过小米OT协议发送控制指令以实现本地化控制功能。只有当上述本地化控制条件不满足时设备控制指令才会通过云端发送。\r\n- 云端:控制指令仅通过云端发送。\r\n### Action 调试模式\r\n对于设备 MIoT-Spec-V2 定义的方法,在生成通知实体之外,还会生成一个文本输入框实体,您可以在调试时用它向设备发送控制指令。\r\n### 隐藏非标准生成实体\r\n隐藏名称以“*”开头的非标准 MIoT-Spec-V2 实例生成的实体。", "description": "## 使用介绍\r\n### 除非您非常清楚下列选项的含义,否则请保持默认。\r\n### 筛选设备\r\n支持按照房间名称和设备类型筛选设备同时也支持设备维度筛选。\r\n### 控制模式\r\n- 自动:本地局域网内存在可用的小米中枢网关时, Home Assistant 会优先通过中枢网关发送设备控制指令以实现本地化控制功能。本地局域网不存在中枢时会尝试通过小米OT协议发送控制指令以实现本地化控制功能。只有当上述本地化控制条件不满足时设备控制指令才会通过云端发送。\r\n- 云端:控制指令仅通过云端发送。\r\n### Action 调试模式\r\n对于设备 MIoT-Spec-V2 定义的方法,在生成通知实体之外,还会生成一个文本输入框实体,您可以在调试时用它向设备发送控制指令。\r\n### 隐藏非标准生成实体\r\n隐藏名称以“*”开头的非标准 MIoT-Spec-V2 实例生成的实体。",
"data": { "data": {
"devices_filter": "筛选设备", "devices_filter": "筛选设备",
"ctrl_mode": "控制模式", "ctrl_mode": "控制模式",
@ -43,8 +43,9 @@
}, },
"devices_filter": { "devices_filter": {
"title": "筛选设备", "title": "筛选设备",
"description": "## 使用介绍\r\n- 支持按照房间名称和设备类型筛选设备,同时也支持设备维度筛选。\r\n- 您也可以进入对应集成项【配置>更新设备列表】页面重新筛选。", "description": "## 使用介绍\r\n支持按照房间名称、设备接入类型、设备型号筛选设备,同时也支持设备维度筛选。\r\n- 统计优先级:排除优先级高于包含优先级,会先取包含项,然后再排除。\r\n- 筛选优先级:筛选设备>筛选设备型号>筛选设备接入类型>筛选家庭房间\r\n### 统计逻辑\r\n- 与逻辑:取所有同模式筛选项的交集。\r\n- 或逻辑:取所有同模式筛选项的并集。\r\n### 筛选模式\r\n- 排除:移除不需要的项。\r\n- 包含:包含需要的项。\r\n- 您也可以进入对应集成项【配置>更新设备列表】页面重新筛选。",
"data": { "data": {
"statistics_logic": "统计逻辑",
"room_filter_mode": "筛选家庭房间", "room_filter_mode": "筛选家庭房间",
"room_list": "家庭房间", "room_list": "家庭房间",
"type_filter_mode": "筛选设备接入类型", "type_filter_mode": "筛选设备接入类型",

View File

@ -33,7 +33,7 @@
}, },
"advanced_options": { "advanced_options": {
"title": "高級設置選項", "title": "高級設置選項",
"description": "## 使用介紹\r\n### 除非您非常清楚下列選項的含義,否則請保持默認。\r\n###篩選設備\r\n支持按照房間名稱和設備類型篩選設備同時也支持設備維度篩選。\r\n### 控制模式\r\n- 自動:本地局域網內存在可用的小米中樞網關時, Home Assistant 會優先通過中樞網關發送設備控制指令以實現本地化控制功能。本地局域網不存在中樞時會嘗試通過小米OT協議發送控制指令以實現本地化控制功能。只有當上述本地化控制條件不滿足時設備控制指令才會通過雲端發送。\r\n- 雲端:控制指令僅通過雲端發送。\r\n### Action 調試模式\r\n對於設備 MIoT-Spec-V2 定義的方法,在生成通知實體之外,還會生成一個文本輸入框實體,您可以在調試時用它向設備發送控制指令。\r\n### 隱藏非標準生成實體\r\n隱藏名稱以“*”開頭的非標準 MIoT-Spec-V2 實例生成的實體。", "description": "## 使用介紹\r\n### 除非您非常清楚下列選項的含義,否則請保持默認。\r\n### 篩選設備\r\n支持按照房間名稱和設備類型篩選設備同時也支持設備維度篩選。\r\n### 控制模式\r\n- 自動:本地局域網內存在可用的小米中樞網關時, Home Assistant 會優先通過中樞網關發送設備控制指令以實現本地化控制功能。本地局域網不存在中樞時會嘗試通過小米OT協議發送控制指令以實現本地化控制功能。只有當上述本地化控制條件不滿足時設備控制指令才會通過雲端發送。\r\n- 雲端:控制指令僅通過雲端發送。\r\n### Action 調試模式\r\n對於設備 MIoT-Spec-V2 定義的方法,在生成通知實體之外,還會生成一個文本輸入框實體,您可以在調試時用它向設備發送控制指令。\r\n### 隱藏非標準生成實體\r\n隱藏名稱以“*”開頭的非標準 MIoT-Spec-V2 實例生成的實體。",
"data": { "data": {
"devices_filter": "篩選設備", "devices_filter": "篩選設備",
"ctrl_mode": "控制模式", "ctrl_mode": "控制模式",
@ -45,6 +45,7 @@
"title": "篩選設備", "title": "篩選設備",
"description": "## 使用介紹\r\n- 支持按照房間名稱和設備類型篩選設備,同時也支持設備維度篩選。\r\n- 您也可以進入對應集成項【配置>更新設備列表】頁面重新篩選。", "description": "## 使用介紹\r\n- 支持按照房間名稱和設備類型篩選設備,同時也支持設備維度篩選。\r\n- 您也可以進入對應集成項【配置>更新設備列表】頁面重新篩選。",
"data": { "data": {
"statistics_logic": "統計邏輯",
"room_filter_mode": "篩選家庭房間", "room_filter_mode": "篩選家庭房間",
"room_list": "家庭房間", "room_list": "家庭房間",
"type_filter_mode": "篩選設備接入類型", "type_filter_mode": "篩選設備接入類型",