mirror of
https://github.com/esphome/esphome.git
synced 2024-11-15 03:28:12 +01:00
Support ignoring discovered devices from the dashboard (#7665)
This commit is contained in:
parent
5b5c2fe71b
commit
ca5c73d170
3 changed files with 71 additions and 0 deletions
|
@ -5,10 +5,14 @@ from collections.abc import Coroutine
|
||||||
import contextlib
|
import contextlib
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
from pathlib import Path
|
||||||
import threading
|
import threading
|
||||||
from typing import TYPE_CHECKING, Any, Callable
|
from typing import TYPE_CHECKING, Any, Callable
|
||||||
|
|
||||||
|
from esphome.storage_json import ignored_devices_storage_path
|
||||||
|
|
||||||
from ..zeroconf import DiscoveredImport
|
from ..zeroconf import DiscoveredImport
|
||||||
from .dns import DNSCache
|
from .dns import DNSCache
|
||||||
from .entries import DashboardEntries
|
from .entries import DashboardEntries
|
||||||
|
@ -20,6 +24,8 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
IGNORED_DEVICES_STORAGE_PATH = "ignored-devices.json"
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Event:
|
class Event:
|
||||||
|
@ -74,6 +80,7 @@ class ESPHomeDashboard:
|
||||||
"settings",
|
"settings",
|
||||||
"dns_cache",
|
"dns_cache",
|
||||||
"_background_tasks",
|
"_background_tasks",
|
||||||
|
"ignored_devices",
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
@ -89,12 +96,30 @@ class ESPHomeDashboard:
|
||||||
self.settings = DashboardSettings()
|
self.settings = DashboardSettings()
|
||||||
self.dns_cache = DNSCache()
|
self.dns_cache = DNSCache()
|
||||||
self._background_tasks: set[asyncio.Task] = set()
|
self._background_tasks: set[asyncio.Task] = set()
|
||||||
|
self.ignored_devices: set[str] = set()
|
||||||
|
|
||||||
async def async_setup(self) -> None:
|
async def async_setup(self) -> None:
|
||||||
"""Setup the dashboard."""
|
"""Setup the dashboard."""
|
||||||
self.loop = asyncio.get_running_loop()
|
self.loop = asyncio.get_running_loop()
|
||||||
self.ping_request = asyncio.Event()
|
self.ping_request = asyncio.Event()
|
||||||
self.entries = DashboardEntries(self)
|
self.entries = DashboardEntries(self)
|
||||||
|
self.load_ignored_devices()
|
||||||
|
|
||||||
|
def load_ignored_devices(self) -> None:
|
||||||
|
storage_path = Path(ignored_devices_storage_path())
|
||||||
|
try:
|
||||||
|
with storage_path.open("r", encoding="utf-8") as f_handle:
|
||||||
|
data = json.load(f_handle)
|
||||||
|
self.ignored_devices = set(data.get("ignored_devices", set()))
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def save_ignored_devices(self) -> None:
|
||||||
|
storage_path = Path(ignored_devices_storage_path())
|
||||||
|
with storage_path.open("w", encoding="utf-8") as f_handle:
|
||||||
|
json.dump(
|
||||||
|
{"ignored_devices": sorted(self.ignored_devices)}, indent=2, fp=f_handle
|
||||||
|
)
|
||||||
|
|
||||||
async def async_run(self) -> None:
|
async def async_run(self) -> None:
|
||||||
"""Run the dashboard."""
|
"""Run the dashboard."""
|
||||||
|
|
|
@ -541,6 +541,46 @@ class ImportRequestHandler(BaseHandler):
|
||||||
self.finish()
|
self.finish()
|
||||||
|
|
||||||
|
|
||||||
|
class IgnoreDeviceRequestHandler(BaseHandler):
|
||||||
|
@authenticated
|
||||||
|
def post(self) -> None:
|
||||||
|
dashboard = DASHBOARD
|
||||||
|
try:
|
||||||
|
args = json.loads(self.request.body.decode())
|
||||||
|
device_name = args["name"]
|
||||||
|
ignore = args["ignore"]
|
||||||
|
except (json.JSONDecodeError, KeyError):
|
||||||
|
self.set_status(400)
|
||||||
|
self.set_header("content-type", "application/json")
|
||||||
|
self.write(json.dumps({"error": "Invalid payload"}))
|
||||||
|
return
|
||||||
|
|
||||||
|
ignored_device = next(
|
||||||
|
(
|
||||||
|
res
|
||||||
|
for res in dashboard.import_result.values()
|
||||||
|
if res.device_name == device_name
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
|
||||||
|
if ignored_device is None:
|
||||||
|
self.set_status(404)
|
||||||
|
self.set_header("content-type", "application/json")
|
||||||
|
self.write(json.dumps({"error": "Device not found"}))
|
||||||
|
return
|
||||||
|
|
||||||
|
if ignore:
|
||||||
|
dashboard.ignored_devices.add(ignored_device.device_name)
|
||||||
|
else:
|
||||||
|
dashboard.ignored_devices.discard(ignored_device.device_name)
|
||||||
|
|
||||||
|
dashboard.save_ignored_devices()
|
||||||
|
|
||||||
|
self.set_status(204)
|
||||||
|
self.finish()
|
||||||
|
|
||||||
|
|
||||||
class DownloadListRequestHandler(BaseHandler):
|
class DownloadListRequestHandler(BaseHandler):
|
||||||
@authenticated
|
@authenticated
|
||||||
@bind_config
|
@bind_config
|
||||||
|
@ -688,6 +728,7 @@ class ListDevicesHandler(BaseHandler):
|
||||||
"project_name": res.project_name,
|
"project_name": res.project_name,
|
||||||
"project_version": res.project_version,
|
"project_version": res.project_version,
|
||||||
"network": res.network,
|
"network": res.network,
|
||||||
|
"ignored": res.device_name in dashboard.ignored_devices,
|
||||||
}
|
}
|
||||||
for res in dashboard.import_result.values()
|
for res in dashboard.import_result.values()
|
||||||
if res.device_name not in configured
|
if res.device_name not in configured
|
||||||
|
@ -1156,6 +1197,7 @@ def make_app(debug=get_bool_env(ENV_DEV)) -> tornado.web.Application:
|
||||||
(f"{rel}prometheus-sd", PrometheusServiceDiscoveryHandler),
|
(f"{rel}prometheus-sd", PrometheusServiceDiscoveryHandler),
|
||||||
(f"{rel}boards/([a-z0-9]+)", BoardsRequestHandler),
|
(f"{rel}boards/([a-z0-9]+)", BoardsRequestHandler),
|
||||||
(f"{rel}version", EsphomeVersionHandler),
|
(f"{rel}version", EsphomeVersionHandler),
|
||||||
|
(f"{rel}ignore-device", IgnoreDeviceRequestHandler),
|
||||||
],
|
],
|
||||||
**app_settings,
|
**app_settings,
|
||||||
)
|
)
|
||||||
|
|
|
@ -28,6 +28,10 @@ def esphome_storage_path() -> str:
|
||||||
return os.path.join(CORE.data_dir, "esphome.json")
|
return os.path.join(CORE.data_dir, "esphome.json")
|
||||||
|
|
||||||
|
|
||||||
|
def ignored_devices_storage_path() -> str:
|
||||||
|
return os.path.join(CORE.data_dir, "ignored-devices.json")
|
||||||
|
|
||||||
|
|
||||||
def trash_storage_path() -> str:
|
def trash_storage_path() -> str:
|
||||||
return CORE.relative_config_path("trash")
|
return CORE.relative_config_path("trash")
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue