Skip to content

Instantly share code, notes, and snippets.

@thzinc
Created October 31, 2023 23:48
Show Gist options
  • Save thzinc/c07ffef02c0500e18629b36488f6f4ee to your computer and use it in GitHub Desktop.
Save thzinc/c07ffef02c0500e18629b36488f6f4ee to your computer and use it in GitHub Desktop.
Minimum viable POC for mDNS to support HomeKit Accessory Protocol in CircuitPython 9.x with mDNS TXT record support
class Accessory:
aid: int
services: list = []
class Service:
type: str
iid: int
characteristics: list = []
hidden: bool
primary: bool
linked: list = []
class Characteristic:
type: str
iid: int
value: any
perms: list = []
ev: bool
description: str
format: str
unit: str
minValue: any
maxValue: any
minStep: any
maxLen: int
maxDataLen: int
valid_values: list
valid_values_range: list
TTL: int
pid: int
class ServiceDiscoveryConfig:
configuration_number: int
feature_flags: int
id: str
model_name: str
protocol_version: str = "1.0"
state_number: int = 1
status_flags: int = 0
accessory_catalog_identifier: int
setup_hash: str
def __init__(
self,
configuration_number: int,
feature_flags: int,
id: str,
model_name: str,
accessory_catalog_identifier: int,
setup_hash: str,
protocol_version: str = "1.0",
state_number: int = 1,
status_flags: int = 0,
) -> None:
self.configuration_number = configuration_number
self.feature_flags = feature_flags
self.id = id
self.model_name = model_name
self.accessory_catalog_identifier = accessory_catalog_identifier
self.setup_hash = setup_hash
self.protocol_version = protocol_version
self.state_number = state_number
self.status_flags = status_flags
def to_txt_record(self) -> list:
pairs = [
f"c#={self.configuration_number}",
f"id={self.id}",
f"md={self.model_name}",
f"pv={self.protocol_version}",
f"s#={self.state_number}",
f"sf={self.status_flags}",
f"ci={self.accessory_catalog_identifier}",
f"sh={self.setup_hash}",
]
if self.feature_flags > 0:
pairs.append(f"ff={self.feature_flags}")
return pairs
import board
import digitalio
import hap
import mdns
import os
import time
import wifi
ssid = os.getenv("WIFI_SSID")
password = os.getenv("WIFI_PASSWORD")
print("Connecting to", ssid)
wifi.radio.connect(ssid, password)
print("Connected to", ssid)
mac = ":".join([f"{i:02x}" for i in wifi.radio.mac_address])
model_name = os.getenv("MODEL_NAME", "Pico")
setup_hash = os.getenv("SETUP_HASH", "336699198")
print(f"MAC: {mac}")
service_discovery_config = hap.ServiceDiscoveryConfig(
configuration_number=3,
feature_flags=0,
id=mac,
model_name=model_name,
status_flags=1,
accessory_catalog_identifier=5, # HACK: 5 is lighting
setup_hash=setup_hash,
)
print(service_discovery_config.to_txt_record())
mdns_server = mdns.Server(wifi.radio)
mdns_server.hostname = "pico"
mdns_server.instance_name = service_discovery_config.model_name
mdns_server.advertise_service(
service_type="_hap",
protocol="_tcp",
port=80,
txt_records=service_discovery_config.to_txt_record(),
)
led = digitalio.DigitalInOut(board.LED)
led.direction = digitalio.Direction.OUTPUT
on = False
while True:
on = not on
led.value = on
time.sleep(0.25)
WIFI_SSID="your_ssid"
WIFI_PASSWORD="your_password"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment