mirror of
https://github.com/esphome/esphome.git
synced 2026-05-23 11:16:52 +08:00
Add local mDNS responder for .local (#386)
* Add local mDNS responder * Fix * Use mDNS in dashboard status * Lint * Lint * Fix test * Remove hostname * Fix use enum * Lint
This commit is contained in:
@@ -24,8 +24,6 @@ RUN \
|
||||
python-pil \
|
||||
# Git for esphomelib downloads
|
||||
git \
|
||||
# Ping for dashboard online/offline status
|
||||
iputils-ping \
|
||||
# NGINX proxy
|
||||
nginx \
|
||||
\
|
||||
|
||||
@@ -22,8 +22,6 @@ RUN \
|
||||
python-pil \
|
||||
# Git for esphomelib downloads
|
||||
git \
|
||||
# Ping for dashboard online/offline status
|
||||
iputils-ping \
|
||||
# NGINX proxy
|
||||
nginx \
|
||||
\
|
||||
|
||||
@@ -454,7 +454,7 @@ def run_logs(config, address):
|
||||
|
||||
wait_time = min(2**tries, 300)
|
||||
if not has_connects:
|
||||
_LOGGER.warning(u"Initial connection failed. The ESP might not be connected"
|
||||
_LOGGER.warning(u"Initial connection failed. The ESP might not be connected "
|
||||
u"to WiFi yet (%s). Re-Trying in %s seconds",
|
||||
error, wait_time)
|
||||
else:
|
||||
|
||||
@@ -3,7 +3,7 @@ import voluptuous as vol
|
||||
from esphomeyaml import pins
|
||||
from esphomeyaml.components import wifi
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.const import CONF_DOMAIN, CONF_HOSTNAME, CONF_ID, CONF_MANUAL_IP, CONF_TYPE, \
|
||||
from esphomeyaml.const import CONF_DOMAIN, CONF_ID, CONF_MANUAL_IP, CONF_TYPE, \
|
||||
ESP_PLATFORM_ESP32
|
||||
from esphomeyaml.cpp_generator import Pvariable, add
|
||||
from esphomeyaml.cpp_helpers import gpio_output_pin_expression
|
||||
@@ -43,7 +43,6 @@ CONFIG_SCHEMA = vol.Schema({
|
||||
vol.Optional(CONF_PHY_ADDR, default=0): vol.All(cv.int_, vol.Range(min=0, max=31)),
|
||||
vol.Optional(CONF_POWER_PIN): pins.gpio_output_pin_schema,
|
||||
vol.Optional(CONF_MANUAL_IP): wifi.STA_MANUAL_IP_SCHEMA,
|
||||
vol.Optional(CONF_HOSTNAME): cv.hostname,
|
||||
vol.Optional(CONF_DOMAIN, default='.local'): cv.domain_name,
|
||||
})
|
||||
|
||||
@@ -63,9 +62,6 @@ def to_code(config):
|
||||
yield
|
||||
add(eth.set_power_pin(pin))
|
||||
|
||||
if CONF_HOSTNAME in config:
|
||||
add(eth.set_hostname(config[CONF_HOSTNAME]))
|
||||
|
||||
if CONF_MANUAL_IP in config:
|
||||
add(eth.set_manual_ip(wifi.manual_ip(config[CONF_MANUAL_IP])))
|
||||
|
||||
|
||||
@@ -111,6 +111,9 @@ CONFIG_SCHEMA = vol.All(vol.Schema({
|
||||
vol.Optional(CONF_REBOOT_TIMEOUT): cv.positive_time_period_milliseconds,
|
||||
vol.Optional(CONF_POWER_SAVE_MODE): cv.one_of(*WIFI_POWER_SAVE_MODES, upper=True),
|
||||
vol.Optional(CONF_FAST_CONNECT): cv.boolean,
|
||||
|
||||
vol.Optional(CONF_HOSTNAME): cv.invalid("The hostname option has been removed in 1.11.0, "
|
||||
"now it's always the node name.")
|
||||
}), validate)
|
||||
|
||||
|
||||
@@ -166,9 +169,6 @@ def to_code(config):
|
||||
if CONF_AP in config:
|
||||
add(wifi.set_ap(wifi_network(config[CONF_AP], config.get(CONF_MANUAL_IP))))
|
||||
|
||||
if CONF_HOSTNAME in config:
|
||||
add(wifi.set_hostname(config[CONF_HOSTNAME]))
|
||||
|
||||
if CONF_REBOOT_TIMEOUT in config:
|
||||
add(wifi.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
|
||||
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import codecs
|
||||
import collections
|
||||
import hmac
|
||||
import json
|
||||
import logging
|
||||
import multiprocessing
|
||||
import os
|
||||
import subprocess
|
||||
import threading
|
||||
@@ -25,7 +23,7 @@ import tornado.websocket
|
||||
|
||||
from esphomeyaml import const
|
||||
from esphomeyaml.__main__ import get_serial_ports
|
||||
from esphomeyaml.helpers import mkdir_p, run_system_command
|
||||
from esphomeyaml.helpers import mkdir_p
|
||||
from esphomeyaml.py_compat import IS_PY2
|
||||
from esphomeyaml.storage_json import EsphomeyamlStorageJSON, StorageJSON, \
|
||||
esphomeyaml_storage_path, ext_storage_path
|
||||
@@ -34,6 +32,8 @@ from esphomeyaml.util import shlex_quote
|
||||
# pylint: disable=unused-import, wrong-import-order
|
||||
from typing import Optional # noqa
|
||||
|
||||
from esphomeyaml.zeroconf import Zeroconf, DashboardStatus
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
CONFIG_DIR = ''
|
||||
PASSWORD_DIGEST = ''
|
||||
@@ -315,55 +315,25 @@ class MainRequestHandler(BaseHandler):
|
||||
get_static_file_url=get_static_file_url)
|
||||
|
||||
|
||||
def _ping_func(filename, address):
|
||||
if os.name == 'nt':
|
||||
command = ['ping', '-n', '1', address]
|
||||
else:
|
||||
command = ['ping', '-c', '1', address]
|
||||
rc, _, _ = run_system_command(*command)
|
||||
return filename, rc == 0
|
||||
|
||||
|
||||
class PingThread(threading.Thread):
|
||||
def run(self):
|
||||
pool = multiprocessing.Pool(processes=8)
|
||||
zc = Zeroconf()
|
||||
|
||||
def on_update(dat):
|
||||
for key, b in dat.items():
|
||||
PING_RESULT[key] = b
|
||||
|
||||
stat = DashboardStatus(zc, on_update)
|
||||
stat.start()
|
||||
while not STOP_EVENT.is_set():
|
||||
# Only do pings if somebody has the dashboard open
|
||||
entries = _list_dashboard_entries()
|
||||
stat.request_query({entry.filename: entry.name + '.local.' for entry in entries})
|
||||
|
||||
PING_REQUEST.wait()
|
||||
PING_REQUEST.clear()
|
||||
|
||||
def callback(ret):
|
||||
PING_RESULT[ret[0]] = ret[1]
|
||||
|
||||
entries = _list_dashboard_entries()
|
||||
queue = collections.deque()
|
||||
for entry in entries:
|
||||
if entry.address is None:
|
||||
PING_RESULT[entry.filename] = None
|
||||
continue
|
||||
|
||||
result = pool.apply_async(_ping_func, (entry.filename, entry.address),
|
||||
callback=callback)
|
||||
queue.append(result)
|
||||
|
||||
while queue:
|
||||
item = queue[0]
|
||||
if item.ready():
|
||||
queue.popleft()
|
||||
continue
|
||||
|
||||
try:
|
||||
item.get(0.1)
|
||||
except OSError:
|
||||
# ping not installed
|
||||
pass
|
||||
except multiprocessing.TimeoutError:
|
||||
pass
|
||||
|
||||
if STOP_EVENT.is_set():
|
||||
pool.terminate()
|
||||
return
|
||||
stat.stop()
|
||||
stat.join()
|
||||
zc.close()
|
||||
|
||||
|
||||
class PingRequestHandler(BaseHandler):
|
||||
|
||||
+26
-3
@@ -7,6 +7,7 @@ import socket
|
||||
import subprocess
|
||||
|
||||
from esphomeyaml.py_compat import text_type, char_to_byte
|
||||
from esphomeyaml.zeroconf import Zeroconf
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -100,12 +101,34 @@ def is_ip_address(host):
|
||||
return False
|
||||
|
||||
|
||||
def _resolve_with_zeroconf(host):
|
||||
from esphomeyaml.core import EsphomeyamlError
|
||||
try:
|
||||
zc = Zeroconf()
|
||||
except Exception:
|
||||
raise EsphomeyamlError("Cannot start mDNS sockets, is this a docker container without "
|
||||
"host network mode?")
|
||||
try:
|
||||
info = zc.resolve_host(host + '.')
|
||||
except Exception as err:
|
||||
raise EsphomeyamlError("Error resolving mDNS hostname: {}".format(err))
|
||||
finally:
|
||||
zc.close()
|
||||
if info is None:
|
||||
raise EsphomeyamlError("Error resolving address with mDNS: Did not respond. "
|
||||
"Maybe the device is offline.")
|
||||
return info
|
||||
|
||||
|
||||
def resolve_ip_address(host):
|
||||
from esphomeyaml.core import EsphomeyamlError
|
||||
|
||||
try:
|
||||
ip = socket.gethostbyname(host)
|
||||
except socket.error as err:
|
||||
from esphomeyaml.core import EsphomeyamlError
|
||||
|
||||
raise EsphomeyamlError("Error resolving IP address: {}".format(err))
|
||||
if host.endswith('.local'):
|
||||
ip = _resolve_with_zeroconf(host)
|
||||
else:
|
||||
raise EsphomeyamlError("Error resolving IP address: {}".format(err))
|
||||
|
||||
return ip
|
||||
|
||||
@@ -62,3 +62,10 @@ def sort_by_cmp(list_, cmp):
|
||||
list_.sort(cmp=cmp)
|
||||
else:
|
||||
list_.sort(key=functools.cmp_to_key(cmp))
|
||||
|
||||
|
||||
def indexbytes(buf, i):
|
||||
if IS_PY3:
|
||||
return buf[i]
|
||||
else:
|
||||
return ord(buf[i])
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,7 @@ disable=
|
||||
too-many-statements,
|
||||
too-many-arguments,
|
||||
too-many-return-statements,
|
||||
too-many-instance-attributes,
|
||||
duplicate-code,
|
||||
invalid-name,
|
||||
cyclic-import,
|
||||
|
||||
@@ -8,3 +8,4 @@ esptool>=2.3.1
|
||||
typing>=3.0.0
|
||||
protobuf>=3.4
|
||||
pyserial>=3.4,<4
|
||||
ifaddr>=0.1.6
|
||||
|
||||
@@ -32,6 +32,7 @@ REQUIRES = [
|
||||
'protobuf>=3.4',
|
||||
'tzlocal>=1.4',
|
||||
'pyserial>=3.4,<4',
|
||||
'ifaddr>=0.1.6',
|
||||
]
|
||||
|
||||
# If you have problems importing platformio and esptool as modules you can set
|
||||
|
||||
@@ -35,7 +35,6 @@ wifi:
|
||||
subnet: 255.255.255.0
|
||||
dns1: 1.1.1.1
|
||||
dns2: 1.2.2.1
|
||||
hostname: myverylonghostname
|
||||
domain: .local
|
||||
reboot_timeout: 120s
|
||||
power_save_mode: none
|
||||
|
||||
Reference in New Issue
Block a user