mirror of
https://github.com/Threnklyn/esphome-dev.git
synced 2026-06-05 04:18:29 +02:00
allow to use MQTT for discovery of IPs if mDNS is no option (#3887)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import base64
|
||||
import binascii
|
||||
import codecs
|
||||
import collections
|
||||
import functools
|
||||
@@ -76,6 +77,10 @@ class DashboardSettings:
|
||||
def status_use_ping(self):
|
||||
return get_bool_env("ESPHOME_DASHBOARD_USE_PING")
|
||||
|
||||
@property
|
||||
def status_use_mqtt(self):
|
||||
return get_bool_env("ESPHOME_DASHBOARD_USE_MQTT")
|
||||
|
||||
@property
|
||||
def using_ha_addon_auth(self):
|
||||
if not self.on_ha_addon:
|
||||
@@ -583,6 +588,12 @@ class DashboardEntry:
|
||||
return None
|
||||
return self.storage.address
|
||||
|
||||
@property
|
||||
def no_mdns(self):
|
||||
if self.storage is None:
|
||||
return None
|
||||
return self.storage.no_mdns
|
||||
|
||||
@property
|
||||
def web_port(self):
|
||||
if self.storage is None:
|
||||
@@ -775,9 +786,12 @@ class MDNSStatusThread(threading.Thread):
|
||||
stat.start()
|
||||
while not STOP_EVENT.is_set():
|
||||
entries = _list_dashboard_entries()
|
||||
stat.request_query(
|
||||
{entry.filename: f"{entry.name}.local." for entry in entries}
|
||||
)
|
||||
hosts = {}
|
||||
for entry in entries:
|
||||
if entry.no_mdns is not True:
|
||||
hosts[entry.filename] = f"{entry.name}.local."
|
||||
|
||||
stat.request_query(hosts)
|
||||
IMPORT_RESULT = imports.import_state
|
||||
|
||||
PING_REQUEST.wait()
|
||||
@@ -801,6 +815,9 @@ class PingStatusThread(threading.Thread):
|
||||
entries = _list_dashboard_entries()
|
||||
queue = collections.deque()
|
||||
for entry in entries:
|
||||
if entry.no_mdns is True:
|
||||
continue
|
||||
|
||||
if entry.address is None:
|
||||
PING_RESULT[entry.filename] = None
|
||||
continue
|
||||
@@ -832,10 +849,67 @@ class PingStatusThread(threading.Thread):
|
||||
PING_REQUEST.clear()
|
||||
|
||||
|
||||
class MqttStatusThread(threading.Thread):
|
||||
def run(self):
|
||||
from esphome import mqtt
|
||||
|
||||
entries = _list_dashboard_entries()
|
||||
|
||||
config = mqtt.config_from_env()
|
||||
topic = "esphome/discover/#"
|
||||
|
||||
def on_message(client, userdata, msg):
|
||||
nonlocal entries
|
||||
|
||||
payload = msg.payload.decode(errors="backslashreplace")
|
||||
if len(payload) > 0:
|
||||
data = json.loads(payload)
|
||||
if "name" not in data:
|
||||
return
|
||||
for entry in entries:
|
||||
if entry.name == data["name"]:
|
||||
PING_RESULT[entry.filename] = True
|
||||
return
|
||||
|
||||
def on_connect(client, userdata, flags, return_code):
|
||||
client.publish("esphome/discover", None, retain=False)
|
||||
|
||||
mqttid = str(binascii.hexlify(os.urandom(6)).decode())
|
||||
|
||||
client = mqtt.prepare(
|
||||
config,
|
||||
[topic],
|
||||
on_message,
|
||||
on_connect,
|
||||
None,
|
||||
None,
|
||||
f"esphome-dashboard-{mqttid}",
|
||||
)
|
||||
client.loop_start()
|
||||
|
||||
while not STOP_EVENT.wait(2):
|
||||
# update entries
|
||||
entries = _list_dashboard_entries()
|
||||
|
||||
# will be set to true on on_message
|
||||
for entry in entries:
|
||||
if entry.no_mdns:
|
||||
PING_RESULT[entry.filename] = False
|
||||
|
||||
client.publish("esphome/discover", None, retain=False)
|
||||
MQTT_PING_REQUEST.wait()
|
||||
MQTT_PING_REQUEST.clear()
|
||||
|
||||
client.disconnect()
|
||||
client.loop_stop()
|
||||
|
||||
|
||||
class PingRequestHandler(BaseHandler):
|
||||
@authenticated
|
||||
def get(self):
|
||||
PING_REQUEST.set()
|
||||
if settings.status_use_mqtt:
|
||||
MQTT_PING_REQUEST.set()
|
||||
self.set_header("content-type", "application/json")
|
||||
self.write(json.dumps(PING_RESULT))
|
||||
|
||||
@@ -910,6 +984,7 @@ PING_RESULT: dict = {}
|
||||
IMPORT_RESULT = {}
|
||||
STOP_EVENT = threading.Event()
|
||||
PING_REQUEST = threading.Event()
|
||||
MQTT_PING_REQUEST = threading.Event()
|
||||
|
||||
|
||||
class LoginHandler(BaseHandler):
|
||||
@@ -1197,6 +1272,11 @@ def start_web_server(args):
|
||||
else:
|
||||
status_thread = MDNSStatusThread()
|
||||
status_thread.start()
|
||||
|
||||
if settings.status_use_mqtt:
|
||||
status_thread_mqtt = MqttStatusThread()
|
||||
status_thread_mqtt.start()
|
||||
|
||||
try:
|
||||
tornado.ioloop.IOLoop.current().start()
|
||||
except KeyboardInterrupt:
|
||||
@@ -1204,5 +1284,8 @@ def start_web_server(args):
|
||||
STOP_EVENT.set()
|
||||
PING_REQUEST.set()
|
||||
status_thread.join()
|
||||
if settings.status_use_mqtt:
|
||||
status_thread_mqtt.join()
|
||||
MQTT_PING_REQUEST.set()
|
||||
if args.socket is not None:
|
||||
os.remove(args.socket)
|
||||
|
||||
Reference in New Issue
Block a user