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:
Otto Winter
2019-02-10 16:57:34 +01:00
committed by GitHub
parent fcf5da66c0
commit d9cf91210e
13 changed files with 837 additions and 63 deletions
-2
View File
@@ -24,8 +24,6 @@ RUN \
python-pil \
# Git for esphomelib downloads
git \
# Ping for dashboard online/offline status
iputils-ping \
# NGINX proxy
nginx \
\
-2
View File
@@ -22,8 +22,6 @@ RUN \
python-pil \
# Git for esphomelib downloads
git \
# Ping for dashboard online/offline status
iputils-ping \
# NGINX proxy
nginx \
\
+1 -1
View File
@@ -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:
+1 -5
View File
@@ -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])))
+3 -3
View File
@@ -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]))
+16 -46
View File
@@ -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
View File
@@ -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
+7
View File
@@ -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
+1
View File
@@ -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,
+1
View File
@@ -8,3 +8,4 @@ esptool>=2.3.1
typing>=3.0.0
protobuf>=3.4
pyserial>=3.4,<4
ifaddr>=0.1.6
+1
View File
@@ -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
-1
View File
@@ -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