diff --git a/tests/test_application.py b/tests/test_application.py index 04d48f6..e34f92e 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -2,6 +2,7 @@ from .async_mock import AsyncMock, MagicMock, patch, sentinel import pytest +import logging import zigpy.types as zigpy_types import zigpy.exceptions @@ -96,3 +97,41 @@ async def mock_get_network_state(): with pytest.raises(zigpy.exceptions.FormationFailure): await app.form_network() + + +@pytest.mark.asyncio +async def test_disconnect_success(app): + api = MagicMock() + + app._api = api + await app.disconnect() + + api.close.assert_called_once() + assert app._api is None + + +@pytest.mark.asyncio +async def test_disconnect_failure(app, caplog): + api = MagicMock() + api.disconnect = MagicMock(side_effect=RuntimeError("Broken")) + + app._api = api + + with caplog.at_level(logging.WARNING): + await app.disconnect() + + assert "disconnect" in caplog.text + + api.close.assert_called_once() + assert app._api is None + + +@pytest.mark.asyncio +async def test_disconnect_multiple(app): + app._api = None + + await app.disconnect() + await app.disconnect() + await app.disconnect() + + assert app._api is None diff --git a/tests/test_uart.py b/tests/test_uart.py index 13f79b1..9d7b19a 100644 --- a/tests/test_uart.py +++ b/tests/test_uart.py @@ -1,6 +1,7 @@ from .async_mock import MagicMock, AsyncMock import pytest +import gpiozero import serial_asyncio import serial.tools.list_ports @@ -173,3 +174,10 @@ def test_is_not_zigate_wifi(): port = '/dev/ttyUSB1' r = common.is_zigate_wifi(port) assert r is False + + +def test_startup_gpio_toggling(monkeypatch): + monkeypatch.setattr(gpiozero.Device, '_default_pin_factory', MagicMock()) + + common.set_pizigate_running_mode() + common.set_pizigate_flashing_mode() diff --git a/zigpy_zigate/__init__.py b/zigpy_zigate/__init__.py index ba58a4d..256d1a5 100644 --- a/zigpy_zigate/__init__.py +++ b/zigpy_zigate/__init__.py @@ -1,5 +1,5 @@ MAJOR_VERSION = 0 MINOR_VERSION = 9 -PATCH_VERSION = '1' +PATCH_VERSION = '2' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) diff --git a/zigpy_zigate/common.py b/zigpy_zigate/common.py index 254b569..0b11a28 100644 --- a/zigpy_zigate/common.py +++ b/zigpy_zigate/common.py @@ -81,8 +81,8 @@ def is_zigate_wifi(port): def set_pizigate_running_mode(): LOGGER.info('Put PiZiGate in running mode') - gpio0 = UnclosableOutputDevice(pin=GPIO_PIN0, initial_state=None) - gpio2 = UnclosableOutputDevice(pin=GPIO_PIN2, initial_state=None) + gpio0 = UnclosableOutputDevice(pin=GPIO_PIN0, initial_value=None) + gpio2 = UnclosableOutputDevice(pin=GPIO_PIN2, initial_value=None) gpio2.on() time.sleep(0.5) @@ -97,8 +97,8 @@ def set_pizigate_running_mode(): def set_pizigate_flashing_mode(): LOGGER.info('Put PiZiGate in flashing mode') - gpio0 = UnclosableOutputDevice(pin=GPIO_PIN0, initial_state=None) - gpio2 = UnclosableOutputDevice(pin=GPIO_PIN2, initial_state=None) + gpio0 = UnclosableOutputDevice(pin=GPIO_PIN0, initial_value=None) + gpio2 = UnclosableOutputDevice(pin=GPIO_PIN2, initial_value=None) gpio2.off() time.sleep(0.5) diff --git a/zigpy_zigate/zigbee/application.py b/zigpy_zigate/zigbee/application.py index 3624249..b0249c6 100644 --- a/zigpy_zigate/zigbee/application.py +++ b/zigpy_zigate/zigbee/application.py @@ -49,11 +49,15 @@ async def connect(self): async def disconnect(self): # TODO: how do you stop the network? Is it possible? - await self._api.reset(wait=False) - if self._api: - self._api.close() - self._api = None + if self._api is not None: + try: + await self._api.reset(wait=False) + except Exception as e: + LOGGER.warning("Failed to reset before disconnect: %s", e) + finally: + self._api.close() + self._api = None async def start_network(self): # TODO: how do you start the network? Is it always automatically started?