v2.3.0 — добавлен инструмент list_devices для диагностики и инвентаризации
This commit is contained in:
+106
-1
@@ -2,7 +2,7 @@
|
|||||||
title: Home Assistant Smart Control
|
title: Home Assistant Smart Control
|
||||||
description: Управление умным домом через Home Assistant REST API с интерпретацией естественного языка.
|
description: Управление умным домом через Home Assistant REST API с интерпретацией естественного языка.
|
||||||
author: ChatGPT (refactored by MiniMax-M3)
|
author: ChatGPT (refactored by MiniMax-M3)
|
||||||
version: 2.2.2
|
version: 2.3.0
|
||||||
license: MIT
|
license: MIT
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -781,3 +781,108 @@ class Tools:
|
|||||||
warnings.append("подходящая сцена не найдена среди " + str(len(all_scripts)))
|
warnings.append("подходящая сцена не найдена среди " + str(len(all_scripts)))
|
||||||
|
|
||||||
return actions
|
return actions
|
||||||
|
|
||||||
|
# ========================================================================
|
||||||
|
# Диагностика / справочник устройств (отдельный инструмент)
|
||||||
|
# ========================================================================
|
||||||
|
def list_devices(
|
||||||
|
self,
|
||||||
|
domain: str = "",
|
||||||
|
device_class: str = "",
|
||||||
|
only_with_state: str = "",
|
||||||
|
show_unavailable: bool = True,
|
||||||
|
limit: int = 50,
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
Получить список устройств из Home Assistant с фильтрами.
|
||||||
|
|
||||||
|
Используется для инвентаризации: какие устройства есть, в каком состоянии,
|
||||||
|
какие из них offline. Полезно для отладки и проверки интеграций.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
domain: фильтр по домену (light, switch, binary_sensor, sensor, climate, ...).
|
||||||
|
Спецзначение "window_door" — окна и двери.
|
||||||
|
Пусто — все домены.
|
||||||
|
device_class: фильтр по device_class атрибуту
|
||||||
|
(door, window, motion, battery, temperature, ...).
|
||||||
|
Пусто — все классы.
|
||||||
|
only_with_state: оставить только с указанным состоянием (on/off/open/closed/...).
|
||||||
|
Пусто — любые.
|
||||||
|
show_unavailable: показывать ли устройства со state="unavailable"/"unknown".
|
||||||
|
limit: максимум устройств в ответе.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Список устройств в формате markdown, сгруппированный по доменам.
|
||||||
|
"""
|
||||||
|
if not self.valves.ha_token:
|
||||||
|
return "Не задан HA Token (Valves)."
|
||||||
|
|
||||||
|
try:
|
||||||
|
states = self._get_states(force=True)
|
||||||
|
except Exception as e:
|
||||||
|
return "Не удалось получить состояния: " + str(e)
|
||||||
|
|
||||||
|
domain = domain.lower().strip()
|
||||||
|
device_class = device_class.lower().strip()
|
||||||
|
only_with_state = only_with_state.lower().strip()
|
||||||
|
|
||||||
|
# Фильтрация
|
||||||
|
filtered: List[Dict[str, Any]] = []
|
||||||
|
for s in states:
|
||||||
|
eid = s["entity_id"]
|
||||||
|
attrs = s.get("attributes", {}) or {}
|
||||||
|
cur_state = (s.get("state", "") or "").lower()
|
||||||
|
dc = (attrs.get("device_class", "") or "").lower()
|
||||||
|
|
||||||
|
# Фильтр по домену
|
||||||
|
if domain:
|
||||||
|
if domain == "window_door":
|
||||||
|
# Спецкатегория: всё что похоже на окно/дверь
|
||||||
|
if dc not in ("door", "window", "garage_door", "lock") and \
|
||||||
|
not any(k in (eid + " " + (attrs.get("friendly_name", "") or "").lower())
|
||||||
|
for k in ["окн", "двер", "форточ", "балкон", "калитк", "ворота", "гараж"]):
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if not eid.startswith(domain + "."):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Фильтр по device_class
|
||||||
|
if device_class and dc != device_class:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Фильтр по состоянию
|
||||||
|
if only_with_state and cur_state != only_with_state:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Скрыть unavailable/unknown
|
||||||
|
if not show_unavailable and cur_state in ("unavailable", "unknown", "none"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
filtered.append(s)
|
||||||
|
|
||||||
|
if not filtered:
|
||||||
|
return (
|
||||||
|
"Устройств не найдено по фильтру "
|
||||||
|
"(domain=" + (domain or "любой")
|
||||||
|
+ ", class=" + (device_class or "любой")
|
||||||
|
+ ", state=" + (only_with_state or "любой") + ")."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Группируем по домену
|
||||||
|
by_domain: Dict[str, List[Dict[str, Any]]] = {}
|
||||||
|
for s in filtered:
|
||||||
|
d = s["entity_id"].split(".", 1)[0]
|
||||||
|
by_domain.setdefault(d, []).append(s)
|
||||||
|
|
||||||
|
lines = ["**Найдено " + str(len(filtered)) + " устройств** (показано до " + str(limit) + "):"]
|
||||||
|
for d in sorted(by_domain.keys()):
|
||||||
|
lines.append("")
|
||||||
|
lines.append("### " + d + " (" + str(len(by_domain[d])) + " шт.)")
|
||||||
|
for s in by_domain[d][:limit]:
|
||||||
|
lines.append(self._format_entity(s))
|
||||||
|
|
||||||
|
if len(filtered) > limit:
|
||||||
|
lines.append("")
|
||||||
|
lines.append("... показано " + str(limit) + " из " + str(len(filtered)) + ". Увеличьте `limit` для полного списка.")
|
||||||
|
|
||||||
|
return "\n".join(lines)
|
||||||
Reference in New Issue
Block a user