From 1cdb70e1c6d7b34e4bff0968e3272f63ebb37543 Mon Sep 17 00:00:00 2001 From: ihidchaos Date: Mon, 28 Oct 2024 10:33:17 +0800 Subject: [PATCH] replase Avahi with ZeroConf for cross platform;add fake LED for testing --- README.md | 9 ++--- circuitmatter/__init__.py | 4 +-- circuitmatter/utility/mdns/zeroconf.py | 47 ++++++++++++++++++++++++++ examples/fake_onoff_led.py | 32 ++++++++++++++++++ examples/replay.py | 4 +-- examples/replay_rgb_light.py | 4 +-- pyproject.toml | 1 + 7 files changed, 88 insertions(+), 13 deletions(-) create mode 100644 circuitmatter/utility/mdns/zeroconf.py create mode 100644 examples/fake_onoff_led.py diff --git a/README.md b/README.md index f76107a..fb0501d 100644 --- a/README.md +++ b/README.md @@ -21,12 +21,7 @@ CircuitMatter is currently developed in CPython 3.12, the de facto implementatio ### Running on a Raspberry Pi SBC -CircuitMatter uses [avahi tools](https://avahi.org) to manage MDNS on Linux. It must therefore be installed for it to work properly. -```shell -sudo apt-get install avahi-utils -``` - -Now, install CircuitMatter: +Install CircuitMatter: ```shell pip install circuitmatter @@ -203,7 +198,7 @@ To run CircuitMatter against a live Matter commissioner run: python examples/replay.py ``` -This will start up MDNS via avahi for discovery by the commissioner and then reply to received UDP packets. CircuitMatter currently doesn't fully commission so it can't act as any specific type of device yet. When it can, there will be examples. +This will start up MDNS for discovery by the commissioner and then reply to received UDP packets. CircuitMatter currently doesn't fully commission so it can't act as any specific type of device yet. When it can, there will be examples. ## Running a Matter commissioner diff --git a/circuitmatter/__init__.py b/circuitmatter/__init__.py index 3cd743f..d2c517f 100644 --- a/circuitmatter/__init__.py +++ b/circuitmatter/__init__.py @@ -37,9 +37,9 @@ def __init__( self.socketpool = socketpool if mdns_server is None: - from circuitmatter.utility.mdns.avahi import Avahi + from circuitmatter.utility.mdns.zeroconf import ZeroConf - mdns_server = Avahi() + mdns_server = ZeroConf() self.mdns_server = mdns_server if random_source is None: diff --git a/circuitmatter/utility/mdns/zeroconf.py b/circuitmatter/utility/mdns/zeroconf.py new file mode 100644 index 0000000..0a7b978 --- /dev/null +++ b/circuitmatter/utility/mdns/zeroconf.py @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +import socket +from zeroconf import IPVersion, ServiceInfo, Zeroconf + +class ZeroConf: + def __init__(self): + self.zeroconf = Zeroconf(ip_version=IPVersion.All) + self.service_infos = {} + + def advertise_service( + self, + service_type, + protocol, + port, + txt_records={}, + subtypes=[], + instance_name="", + ): + txt_records = [f"{key}={value}" for key, value in txt_records.items()] + main_info = ServiceInfo( + f"{service_type}.{protocol}.local", + instance_name, + addresses=[socket.inet_aton("0.0.0.0")], + port=port, + properties=txt_records, + ) + + sub_info = ServiceInfo( + subtypes, + instance_name, + addresses=[socket.inet_aton("0.0.0.0")], + port=port, + properties=txt_records, + ) + + self.zeroconf.register_service(main_info) + self.zeroconf.register_service(sub_info) + self.service_infos[service_type + instance_name] = main_info + self.service_infos[subtypes + instance_name] = sub_info + + def __del__(self): + for service_info in self.service_infos.values(): + self.zeroconf.unregister_service(service_info) + self.zeroconf.close() diff --git a/examples/fake_onoff_led.py b/examples/fake_onoff_led.py new file mode 100644 index 0000000..a777994 --- /dev/null +++ b/examples/fake_onoff_led.py @@ -0,0 +1,32 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +"""Simple fake LED on and off as a light.""" + +import circuitmatter as cm +from circuitmatter.device_types.lighting import on_off + + +class LED(on_off.OnOffLight): + def __init__(self, name, led): + super().__init__(name) + self._name = name + self._led = led + + def on(self): + self._led.value = True + print("Led %s is On", self._name) + + def off(self): + self._led.value = False + print("Led %s is Off", self._name) + + +matter = cm.CircuitMatter() +led = LED("led1") +matter.add_device(led) +led = LED("led2") +matter.add_device(led) +while True: + matter.process_packets() diff --git a/examples/replay.py b/examples/replay.py index 7b736c5..c521319 100644 --- a/examples/replay.py +++ b/examples/replay.py @@ -13,7 +13,7 @@ from circuitmatter.device_types.lighting import on_off from circuitmatter.utility import random from circuitmatter.utility.mdns import DummyMDNS -from circuitmatter.utility.mdns.avahi import Avahi +from circuitmatter.utility.mdns.zeroconf import ZeroConf from circuitmatter.utility.recording import RecordingRandom, RecordingSocketPool from circuitmatter.utility.replay import ReplayRandom, ReplaySocketPool @@ -51,7 +51,7 @@ def run(replay_file=None): # No starting state. record_file.write("none\n") socketpool = RecordingSocketPool(record_file, socket) - mdns_server = Avahi() + mdns_server = ZeroConf() random_source = RecordingRandom(record_file, random) matter = cm.CircuitMatter(socketpool, mdns_server, random_source, device_state) diff --git a/examples/replay_rgb_light.py b/examples/replay_rgb_light.py index da1c932..6e05f07 100644 --- a/examples/replay_rgb_light.py +++ b/examples/replay_rgb_light.py @@ -13,7 +13,7 @@ from circuitmatter.device_types.lighting import extended_color from circuitmatter.utility import random from circuitmatter.utility.mdns import DummyMDNS -from circuitmatter.utility.mdns.avahi import Avahi +from circuitmatter.utility.mdns.zeroconf import ZeroConf from circuitmatter.utility.recording import RecordingRandom, RecordingSocketPool from circuitmatter.utility.replay import ReplayRandom, ReplaySocketPool @@ -73,7 +73,7 @@ def run(replay_file=None): # No starting state. record_file.write("none\n") socketpool = RecordingSocketPool(record_file, socket) - mdns_server = Avahi() + mdns_server = ZeroConf() random_source = RecordingRandom(record_file, random) matter = cm.CircuitMatter(socketpool, mdns_server, random_source, device_state) diff --git a/pyproject.toml b/pyproject.toml index 0e96bc8..fc8697b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,6 +7,7 @@ requires = [ "setuptools", "wheel", "setuptools-scm", + "zeroconf", ] [project]