From f78b2c48a7e6a1f570327f28974ae345e97d0971 Mon Sep 17 00:00:00 2001
From: Blake Blackshear <blakeb@blakeshome.com>
Date: Thu, 3 Dec 2020 08:00:23 -0600
Subject: [PATCH] add zeroconf discovery

---
 docker/Dockerfile.base |  1 +
 frigate/app.py         |  2 ++
 frigate/zeroconf.py    | 58 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+)
 create mode 100644 frigate/zeroconf.py

diff --git a/docker/Dockerfile.base b/docker/Dockerfile.base
index 4b43c46a1..372f45953 100644
--- a/docker/Dockerfile.base
+++ b/docker/Dockerfile.base
@@ -30,6 +30,7 @@ RUN apt-get -qq update \
 
 RUN pip3 install \
     peewee \
+    zeroconf \
     voluptuous
 
 COPY nginx/nginx.conf /etc/nginx/nginx.conf
diff --git a/frigate/app.py b/frigate/app.py
index a773b9067..a73823d61 100644
--- a/frigate/app.py
+++ b/frigate/app.py
@@ -20,6 +20,7 @@ from frigate.object_processing import TrackedObjectProcessor
 from frigate.record import RecordingMaintainer
 from frigate.video import capture_camera, track_camera
 from frigate.watchdog import FrigateWatchdog
+from frigate.zeroconf import broadcast_zeroconf
 
 logger = logging.getLogger(__name__)
 
@@ -152,6 +153,7 @@ class FrigateApp():
         self.start_event_cleanup()
         self.start_recording_maintainer()
         self.start_watchdog()
+        self.zeroconf = broadcast_zeroconf(self.config.mqtt.client_id)
         self.flask_app.run(host='127.0.0.1', port=5001, debug=False)
         self.stop()
     
diff --git a/frigate/zeroconf.py b/frigate/zeroconf.py
new file mode 100644
index 000000000..4e8f0f5f0
--- /dev/null
+++ b/frigate/zeroconf.py
@@ -0,0 +1,58 @@
+import logging
+import socket
+
+from zeroconf import (
+    ServiceInfo,
+    NonUniqueNameException,
+    InterfaceChoice,
+    IPVersion,
+    Zeroconf,
+)
+
+logger = logging.getLogger(__name__)
+
+ZEROCONF_TYPE = "_frigate._tcp.local."
+
+# Taken from: http://stackoverflow.com/a/11735897
+def get_local_ip() -> str:
+    """Try to determine the local IP address of the machine."""
+    try:
+        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+
+        # Use Google Public DNS server to determine own IP
+        sock.connect(("8.8.8.8", 80))
+
+        return sock.getsockname()[0]  # type: ignore
+    except OSError:
+        try:
+            return socket.gethostbyname(socket.gethostname())
+        except socket.gaierror:
+            return "127.0.0.1"
+    finally:
+        sock.close()
+
+def broadcast_zeroconf(frigate_id):
+    zeroconf = Zeroconf(interfaces=InterfaceChoice.Default, ip_version=IPVersion.V4Only)
+
+    host_ip = get_local_ip()
+
+    try:
+        host_ip_pton = socket.inet_pton(socket.AF_INET, host_ip)
+    except OSError:
+        host_ip_pton = socket.inet_pton(socket.AF_INET6, host_ip)
+
+    info = ServiceInfo(
+        ZEROCONF_TYPE,
+        name=f"{frigate_id}.{ZEROCONF_TYPE}",
+        addresses=[host_ip_pton],
+        port=5000,
+    )
+
+    logger.info("Starting Zeroconf broadcast")
+    try:
+        zeroconf.register_service(info)
+    except NonUniqueNameException:
+        logger.error(
+            "Frigate instance with identical name present in the local network"
+        )
+    return zeroconf
\ No newline at end of file