Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 1.8.0

- Fix ZeroConf

## 1.7.2

- Fix event data being `None`
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "wyoming"
version = "1.7.2"
version = "1.8.0"
description = "Peer-to-peer protocol for voice assistants"
readme = "README.md"
requires-python = ">=3.8"
Expand Down
56 changes: 40 additions & 16 deletions wyoming/zeroconf.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#!/usr/bin/env python3
"""Runs mDNS zeroconf service for Home Assistant discovery."""

import logging
import socket
import uuid
from typing import Optional

_LOGGER = logging.getLogger(__name__)
Expand All @@ -15,21 +16,44 @@
MDNS_TARGET_IP = "224.0.0.251"


async def register_server(name: str, port: int, host: Optional[str] = None) -> None:
if not host:
test_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
test_sock.setblocking(False)
test_sock.connect((MDNS_TARGET_IP, 1))
host = test_sock.getsockname()[0]
_LOGGER.debug("Detected IP: %s", host)
class HomeAssistantZeroconf:
"""ZeroConf (mDNS) discovery for Home Assistant."""

def __init__(
self, port: int, name: Optional[str] = None, host: Optional[str] = None
) -> None:
self.port = port
self.name = name or _get_mac_address()

if not host:
test_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
test_sock.setblocking(False)
test_sock.connect((MDNS_TARGET_IP, 1))
host = test_sock.getsockname()[0]
_LOGGER.debug("Detected IP: %s", host)

assert host
self.host = host
self._aiozc = AsyncZeroconf()

async def register_server(self) -> None:
"""Register ZeroConf server."""

service_info = AsyncServiceInfo(
"_wyoming._tcp.local.",
f"{self.name}._wyoming._tcp.local.",
addresses=[socket.inet_aton(self.host)],
port=self.port,
)
await self._aiozc.async_register_service(service_info)
_LOGGER.debug("Zeroconf discovery enabled: %s", service_info)

assert host

service_info = AsyncServiceInfo(
"_wyoming._tcp.local.",
f"{name}._wyoming._tcp.local.",
addresses=[socket.inet_aton(host)],
port=port,
def _get_mac_address() -> str:
"""Return MAC address formatted as hex with no colons."""
return "".join(
# pylint: disable=consider-using-f-string
["{:02x}".format((uuid.getnode() >> ele) & 0xFF) for ele in range(0, 8 * 6, 8)][
::-1
]
)
aiozc = AsyncZeroconf()
await aiozc.async_register_service(service_info)