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