mirror of
https://github.com/esphome/esphome.git
synced 2025-02-12 16:08:19 +00:00
tornado support native coros
This commit is contained in:
parent
e4d9a87af2
commit
9194c82213
@ -289,7 +289,7 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler):
|
|||||||
self._use_popen = os.name == "nt"
|
self._use_popen = os.name == "nt"
|
||||||
|
|
||||||
@authenticated
|
@authenticated
|
||||||
def on_message(self, message):
|
async def on_message(self, message):
|
||||||
# Messages are always JSON, 500 when not
|
# Messages are always JSON, 500 when not
|
||||||
json_message = json.loads(message)
|
json_message = json.loads(message)
|
||||||
type_ = json_message["type"]
|
type_ = json_message["type"]
|
||||||
@ -299,14 +299,14 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler):
|
|||||||
_LOGGER.warning("Requested unknown message type %s", type_)
|
_LOGGER.warning("Requested unknown message type %s", type_)
|
||||||
return
|
return
|
||||||
|
|
||||||
handlers[type_](self, json_message)
|
await handlers[type_](self, json_message)
|
||||||
|
|
||||||
@websocket_method("spawn")
|
@websocket_method("spawn")
|
||||||
def handle_spawn(self, json_message):
|
async def handle_spawn(self, json_message):
|
||||||
if self._proc is not None:
|
if self._proc is not None:
|
||||||
# spawn can only be called once
|
# spawn can only be called once
|
||||||
return
|
return
|
||||||
command = self.build_command(json_message)
|
command = await self.build_command(json_message)
|
||||||
_LOGGER.info("Running command '%s'", " ".join(shlex_quote(x) for x in command))
|
_LOGGER.info("Running command '%s'", " ".join(shlex_quote(x) for x in command))
|
||||||
|
|
||||||
if self._use_popen:
|
if self._use_popen:
|
||||||
@ -337,7 +337,7 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler):
|
|||||||
return self._proc is not None and self._proc.returncode is None
|
return self._proc is not None and self._proc.returncode is None
|
||||||
|
|
||||||
@websocket_method("stdin")
|
@websocket_method("stdin")
|
||||||
def handle_stdin(self, json_message):
|
async def handle_stdin(self, json_message):
|
||||||
if not self.is_process_active:
|
if not self.is_process_active:
|
||||||
return
|
return
|
||||||
data = json_message["data"]
|
data = json_message["data"]
|
||||||
@ -395,7 +395,7 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler):
|
|||||||
# Shutdown proc on WS close
|
# Shutdown proc on WS close
|
||||||
self._is_closed = True
|
self._is_closed = True
|
||||||
|
|
||||||
def build_command(self, json_message):
|
async def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
@ -405,7 +405,9 @@ DASHBOARD_COMMAND = ["esphome", "--dashboard"]
|
|||||||
class EsphomePortCommandWebSocket(EsphomeCommandWebSocket):
|
class EsphomePortCommandWebSocket(EsphomeCommandWebSocket):
|
||||||
"""Base class for commands that require a port."""
|
"""Base class for commands that require a port."""
|
||||||
|
|
||||||
def run_command(self, args: list[str], json_message: dict[str, Any]) -> list[str]:
|
async def run_command(
|
||||||
|
self, args: list[str], json_message: dict[str, Any]
|
||||||
|
) -> list[str]:
|
||||||
"""Build the command to run."""
|
"""Build the command to run."""
|
||||||
configuration = json_message["configuration"]
|
configuration = json_message["configuration"]
|
||||||
config_file = settings.rel_path(configuration)
|
config_file = settings.rel_path(configuration)
|
||||||
@ -414,7 +416,7 @@ class EsphomePortCommandWebSocket(EsphomeCommandWebSocket):
|
|||||||
port == "OTA"
|
port == "OTA"
|
||||||
and (mdns := MDNS_CONTAINER.get_mdns())
|
and (mdns := MDNS_CONTAINER.get_mdns())
|
||||||
and (host_name := mdns.filename_to_host_name_thread_safe(configuration))
|
and (host_name := mdns.filename_to_host_name_thread_safe(configuration))
|
||||||
and (address := mdns.resolve_host_thread_safe(host_name))
|
and (address := await mdns.async_resolve_host(host_name))
|
||||||
):
|
):
|
||||||
port = address
|
port = address
|
||||||
|
|
||||||
@ -428,15 +430,15 @@ class EsphomePortCommandWebSocket(EsphomeCommandWebSocket):
|
|||||||
|
|
||||||
|
|
||||||
class EsphomeLogsHandler(EsphomePortCommandWebSocket):
|
class EsphomeLogsHandler(EsphomePortCommandWebSocket):
|
||||||
def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
async def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
||||||
"""Build the command to run."""
|
"""Build the command to run."""
|
||||||
return self.run_command(["logs"], json_message)
|
return await self.run_command(["logs"], json_message)
|
||||||
|
|
||||||
|
|
||||||
class EsphomeRenameHandler(EsphomeCommandWebSocket):
|
class EsphomeRenameHandler(EsphomeCommandWebSocket):
|
||||||
old_name: str
|
old_name: str
|
||||||
|
|
||||||
def build_command(self, json_message):
|
async def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
||||||
config_file = settings.rel_path(json_message["configuration"])
|
config_file = settings.rel_path(json_message["configuration"])
|
||||||
self.old_name = json_message["configuration"]
|
self.old_name = json_message["configuration"]
|
||||||
return [
|
return [
|
||||||
@ -457,19 +459,19 @@ class EsphomeRenameHandler(EsphomeCommandWebSocket):
|
|||||||
|
|
||||||
|
|
||||||
class EsphomeUploadHandler(EsphomePortCommandWebSocket):
|
class EsphomeUploadHandler(EsphomePortCommandWebSocket):
|
||||||
def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
async def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
||||||
"""Build the command to run."""
|
"""Build the command to run."""
|
||||||
return self.run_command(["upload"], json_message)
|
return self.run_command(["upload"], json_message)
|
||||||
|
|
||||||
|
|
||||||
class EsphomeRunHandler(EsphomePortCommandWebSocket):
|
class EsphomeRunHandler(EsphomePortCommandWebSocket):
|
||||||
def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
async def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
||||||
"""Build the command to run."""
|
"""Build the command to run."""
|
||||||
return self.run_command(["run"], json_message)
|
return self.run_command(["run"], json_message)
|
||||||
|
|
||||||
|
|
||||||
class EsphomeCompileHandler(EsphomeCommandWebSocket):
|
class EsphomeCompileHandler(EsphomeCommandWebSocket):
|
||||||
def build_command(self, json_message):
|
async def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
||||||
config_file = settings.rel_path(json_message["configuration"])
|
config_file = settings.rel_path(json_message["configuration"])
|
||||||
command = [*DASHBOARD_COMMAND, "compile"]
|
command = [*DASHBOARD_COMMAND, "compile"]
|
||||||
if json_message.get("only_generate", False):
|
if json_message.get("only_generate", False):
|
||||||
@ -479,7 +481,7 @@ class EsphomeCompileHandler(EsphomeCommandWebSocket):
|
|||||||
|
|
||||||
|
|
||||||
class EsphomeValidateHandler(EsphomeCommandWebSocket):
|
class EsphomeValidateHandler(EsphomeCommandWebSocket):
|
||||||
def build_command(self, json_message):
|
async def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
||||||
config_file = settings.rel_path(json_message["configuration"])
|
config_file = settings.rel_path(json_message["configuration"])
|
||||||
command = [*DASHBOARD_COMMAND, "config", config_file]
|
command = [*DASHBOARD_COMMAND, "config", config_file]
|
||||||
if not settings.streamer_mode:
|
if not settings.streamer_mode:
|
||||||
@ -488,29 +490,29 @@ class EsphomeValidateHandler(EsphomeCommandWebSocket):
|
|||||||
|
|
||||||
|
|
||||||
class EsphomeCleanMqttHandler(EsphomeCommandWebSocket):
|
class EsphomeCleanMqttHandler(EsphomeCommandWebSocket):
|
||||||
def build_command(self, json_message):
|
async def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
||||||
config_file = settings.rel_path(json_message["configuration"])
|
config_file = settings.rel_path(json_message["configuration"])
|
||||||
return [*DASHBOARD_COMMAND, "clean-mqtt", config_file]
|
return [*DASHBOARD_COMMAND, "clean-mqtt", config_file]
|
||||||
|
|
||||||
|
|
||||||
class EsphomeCleanHandler(EsphomeCommandWebSocket):
|
class EsphomeCleanHandler(EsphomeCommandWebSocket):
|
||||||
def build_command(self, json_message):
|
async def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
||||||
config_file = settings.rel_path(json_message["configuration"])
|
config_file = settings.rel_path(json_message["configuration"])
|
||||||
return [*DASHBOARD_COMMAND, "clean", config_file]
|
return [*DASHBOARD_COMMAND, "clean", config_file]
|
||||||
|
|
||||||
|
|
||||||
class EsphomeVscodeHandler(EsphomeCommandWebSocket):
|
class EsphomeVscodeHandler(EsphomeCommandWebSocket):
|
||||||
def build_command(self, json_message):
|
async def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
||||||
return [*DASHBOARD_COMMAND, "-q", "vscode", "dummy"]
|
return [*DASHBOARD_COMMAND, "-q", "vscode", "dummy"]
|
||||||
|
|
||||||
|
|
||||||
class EsphomeAceEditorHandler(EsphomeCommandWebSocket):
|
class EsphomeAceEditorHandler(EsphomeCommandWebSocket):
|
||||||
def build_command(self, json_message):
|
async def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
||||||
return [*DASHBOARD_COMMAND, "-q", "vscode", "--ace", settings.config_dir]
|
return [*DASHBOARD_COMMAND, "-q", "vscode", "--ace", settings.config_dir]
|
||||||
|
|
||||||
|
|
||||||
class EsphomeUpdateAllHandler(EsphomeCommandWebSocket):
|
class EsphomeUpdateAllHandler(EsphomeCommandWebSocket):
|
||||||
def build_command(self, json_message):
|
async def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
||||||
return [*DASHBOARD_COMMAND, "update-all", settings.config_dir]
|
return [*DASHBOARD_COMMAND, "update-all", settings.config_dir]
|
||||||
|
|
||||||
|
|
||||||
@ -990,12 +992,12 @@ class MDNSStatusThread(threading.Thread):
|
|||||||
"""Resolve a filename to an address in a thread-safe manner."""
|
"""Resolve a filename to an address in a thread-safe manner."""
|
||||||
return self.filename_to_host_name.get(filename)
|
return self.filename_to_host_name.get(filename)
|
||||||
|
|
||||||
def resolve_host_thread_safe(self, host_name: str) -> str | None:
|
async def async_resolve_host(self, host_name: str) -> str | None:
|
||||||
"""Resolve a host name to an address in a thread-safe manner."""
|
"""Resolve a host name to an address in a thread-safe manner."""
|
||||||
if zc := self.zeroconf:
|
if zc := self.zeroconf:
|
||||||
# Currently we do not do any I/O and only
|
# Currently we do not do any I/O and only
|
||||||
# return the cached result (timeout=0)
|
# return the cached result (timeout=0)
|
||||||
return zc.resolve_host(host_name, 0)
|
return await zc.async_resolve_host(host_name)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _refresh_hosts(self):
|
def _refresh_hosts(self):
|
||||||
|
@ -147,13 +147,28 @@ class DashboardImportDiscovery:
|
|||||||
|
|
||||||
|
|
||||||
class EsphomeZeroconf(Zeroconf):
|
class EsphomeZeroconf(Zeroconf):
|
||||||
def resolve_host(self, host: str, timeout: float = 3.0) -> str | None:
|
def _make_host_resolver(self, host: str) -> HostResolver:
|
||||||
"""Resolve a host name to an IP address."""
|
"""Create a new HostResolver for the given host name."""
|
||||||
name = host.partition(".")[0]
|
name = host.partition(".")[0]
|
||||||
info = HostResolver(ESPHOME_SERVICE_TYPE, f"{name}.{ESPHOME_SERVICE_TYPE}")
|
info = HostResolver(ESPHOME_SERVICE_TYPE, f"{name}.{ESPHOME_SERVICE_TYPE}")
|
||||||
|
return info
|
||||||
|
|
||||||
|
def resolve_host(self, host: str, timeout: float = 3.0) -> str | None:
|
||||||
|
"""Resolve a host name to an IP address."""
|
||||||
|
info = self._make_host_resolver(host)
|
||||||
if (
|
if (
|
||||||
info.load_from_cache(self)
|
info.load_from_cache(self)
|
||||||
or (timeout and info.request(self, timeout * 1000))
|
or (timeout and info.request(self, timeout * 1000))
|
||||||
) and (addresses := info.ip_addresses_by_version(IPVersion.V4Only)):
|
) and (addresses := info.ip_addresses_by_version(IPVersion.V4Only)):
|
||||||
return str(addresses[0])
|
return str(addresses[0])
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
async def async_resolve_host(self, host: str, timeout: float = 3.0) -> str | None:
|
||||||
|
"""Resolve a host name to an IP address."""
|
||||||
|
info = self._make_host_resolver(host)
|
||||||
|
if (
|
||||||
|
info.load_from_cache(self)
|
||||||
|
or (timeout and await info.async_request(self, timeout * 1000))
|
||||||
|
) and (addresses := info.ip_addresses_by_version(IPVersion.V4Only)):
|
||||||
|
return str(addresses[0])
|
||||||
|
return None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user