v2.3.0 — добавлен инструмент list_devices для диагностики и инвентаризации
This commit is contained in:
+107
-2
@@ -2,7 +2,7 @@
|
||||
title: Home Assistant Smart Control
|
||||
description: Управление умным домом через Home Assistant REST API с интерпретацией естественного языка.
|
||||
author: ChatGPT (refactored by MiniMax-M3)
|
||||
version: 2.2.2
|
||||
version: 2.3.0
|
||||
license: MIT
|
||||
"""
|
||||
|
||||
@@ -780,4 +780,109 @@ class Tools:
|
||||
else:
|
||||
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