diff --git a/accessories/AudioReceiver.py b/accessories/AudioReceiver.py new file mode 100644 index 00000000..b925c67e --- /dev/null +++ b/accessories/AudioReceiver.py @@ -0,0 +1,59 @@ +"""A sample audio receiver (AV receiver) accessory. + +Demonstrates the ``CATEGORY_AUDIO_RECEIVER`` category together with the +``Speaker`` service, so the accessory shows up with the receiver tile in +the Home app. +""" +import logging +import signal + +from pyhap.accessory import Accessory +from pyhap.accessory_driver import AccessoryDriver +from pyhap.const import CATEGORY_AUDIO_RECEIVER + + +class AudioReceiver(Accessory): + """Fake audio receiver, logs what the client sets.""" + + category = CATEGORY_AUDIO_RECEIVER + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.set_info_service( + manufacturer='HaPK', + model='Sample AV Receiver', + firmware_revision='1.0', + serial_number='1' + ) + + speaker_service = self.add_preload_service( + 'Speaker', ['Mute', 'Volume', 'Active'], + ) + self._mute = speaker_service.configure_char( + 'Mute', value=False, setter_callback=self._on_mute, + ) + self._volume = speaker_service.configure_char( + 'Volume', value=25, setter_callback=self._on_volume, + ) + speaker_service.configure_char('Active', value=1) + + def _on_mute(self, value): + print('Mute' if value else 'Unmute') + + def _on_volume(self, value): + print('Set volume to %s' % value) + + +def main(): + logging.basicConfig(level=logging.INFO) + + driver = AccessoryDriver(port=51826) + driver.add_accessory(accessory=AudioReceiver(driver, 'Audio Receiver')) + + signal.signal(signal.SIGTERM, driver.signal_handler) + driver.start() + + +if __name__ == '__main__': + main() diff --git a/docs/source/intro/examples.rst b/docs/source/intro/examples.rst index bb042f59..de615ab9 100644 --- a/docs/source/intro/examples.rst +++ b/docs/source/intro/examples.rst @@ -28,6 +28,9 @@ device. changes its value from a background ``run`` task. * - ``TV.py``, ``FakeFan.py``, ``DisplaySwitch.py`` - TVs, fans and switches: services with several linked characteristics. + * - ``AudioReceiver.py`` + - An audio receiver: the ``CATEGORY_AUDIO_RECEIVER`` category with a + ``Speaker`` service for volume and mute. * - ``BMP180.py``, ``AM2302.py``, ``TSL2591.py``, ``SDS011.py`` - Reading real hardware (I²C, GPIO, serial) and publishing it, polled from ``run`` with ``run_at_interval``. diff --git a/pyhap/const.py b/pyhap/const.py index aa9468ab..6a3d3d7c 100644 --- a/pyhap/const.py +++ b/pyhap/const.py @@ -50,6 +50,7 @@ CATEGORY_SHOWER_HEAD = 30 CATEGORY_TELEVISION = 31 CATEGORY_TARGET_CONTROLLER = 32 # Remote Controller +CATEGORY_AUDIO_RECEIVER = 34 # Audio Receiver # ### HAP Permissions ### diff --git a/tests/test_accessory.py b/tests/test_accessory.py index 8f1885bd..18d5ca88 100644 --- a/tests/test_accessory.py +++ b/tests/test_accessory.py @@ -11,6 +11,7 @@ from pyhap.accessory import Accessory, Bridge from pyhap.accessory_driver import AccessoryDriver from pyhap.const import ( + CATEGORY_AUDIO_RECEIVER, CATEGORY_CAMERA, CATEGORY_TARGET_CONTROLLER, CATEGORY_TELEVISION, @@ -202,6 +203,13 @@ def test_xhm_uri(mock_driver: Any) -> None: mock_driver.state.setup_id = "BBBB" assert acc_1.xhm_uri() == "X-HM://00VPU8UEKBBBB" + acc_1.category = CATEGORY_AUDIO_RECEIVER + mock_driver.state = State( + address="1.2.3.4", mac="AA::BB::CC::DD::EE", pincode=b"323-23-1212", port=44 + ) + mock_driver.state.setup_id = "BBBB" + assert acc_1.xhm_uri() == "X-HM://00XOVCWDOBBBB" + def test_set_info_service(mock_driver: Any) -> None: acc_1 = Accessory(mock_driver, "Test Accessory 1", aid=2)