Пример #1
0
async def test_set_color(client):
    """Test setting light color."""
    light = Light("00:11:22")
    await light.connect()

    await light.set_color(255, 255, 255)
    client.write_gatt_char.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb',
        b'\x56\xFF\xFF\xFF\x00\xF0\xAA')

    await light.set_color(64, 128, 192)
    client.write_gatt_char.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb',
        b'\x56\x08\x10\x18\x00\xF0\xAA')

    # Assert that lights are always on unless zero
    await light.set_color(1, 1, 1)
    client.write_gatt_char.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb',
        b'\x56\x01\x01\x01\x00\xF0\xAA')

    # When called with all zeros, just turn off the light
    await light.set_color(0, 0, 0)
    client.write_gatt_char.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb', b'\xCC\x24\x33')

    with pytest.raises(ValueError):
        await light.set_color(999, 999, 999)

    light._write = MagicMock()
    light._write.side_effect = asyncio.TimeoutError("Mock timeout")

    with pytest.raises(ZerprocException):
        await light.set_color(255, 255, 255)
Пример #2
0
async def test_turn_off(client):
    """Test turning off the light."""
    light = Light("00:11:22")
    await light.connect()

    await light.turn_off()

    client.write_gatt_char.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb', b'\xCC\x24\x33')

    light._write = MagicMock()
    light._write.side_effect = asyncio.TimeoutError("Mock timeout")

    with pytest.raises(ZerprocException):
        await light.turn_off()
Пример #3
0
async def test_connect_exception(client):
    """Test an exception while connecting."""
    light = Light("00:11:22")

    client.connect.side_effect = bleak.exc.BleakError("TEST")

    with pytest.raises(ZerprocException):
        await light.connect()
Пример #4
0
def test_turn_off(device):
    """Test the CLI."""
    light = Light("00:11:22")
    light.connect()

    light.turn_off()

    device.char_write.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb', b'\xCC\x24\x33')
Пример #5
0
async def test_connect_disconnect(client_class, client):
    """Test connecting and disconnecting."""
    light = Light("00:11:22")

    client_class.assert_called_with("00:11:22")

    await light.connect()

    client.connect.assert_called_once()
    client.start_notify.assert_called_once()
    client.start_notify.assert_called_with(
        "0000ffe4-0000-1000-8000-00805f9b34fb", light._handle_data)

    await light.disconnect()

    client.disconnect.assert_called_once()
    client.stop_notify.assert_called_once()
    client.stop_notify.assert_called_with(
        "0000ffe4-0000-1000-8000-00805f9b34fb")
Пример #6
0
async def test_exception_wrapping(client):
    """Test that exceptions are wrapped."""
    light = Light("00:11:22")
    await light.connect()

    client.is_connected.side_effect = bleak.exc.BleakError("TEST")

    with pytest.raises(ZerprocException):
        await light.is_connected()

    client.write_gatt_char.side_effect = bleak.exc.BleakError("TEST")

    with pytest.raises(ZerprocException):
        await light.turn_on()

    # Upstream misses some None checks and doesn't wrap the exceptions
    client.write_gatt_char.side_effect = AttributeError("TEST")

    with pytest.raises(ZerprocException):
        await light.turn_on()
Пример #7
0
async def test_is_connected(client):
    """Test turning on the light."""
    light = Light("00:11:22")
    await light.connect()

    connected = False

    async def is_connected():
        nonlocal connected
        return connected

    client.is_connected.side_effect = is_connected

    assert not await light.is_connected()

    connected = True

    assert await light.is_connected()

    client.is_connected.side_effect = asyncio.TimeoutError("Mock timeout")

    assert not await light.is_connected()
Пример #8
0
def test_get_state(device, mocker):
    """Test the CLI."""
    light = Light("00:11:22")
    light.connect()

    def send_response(*args, **kwargs):
        """Simulate a response from the light"""
        light._handle_data(
            63, b'\x66\xe3\x24\x16\x24\x01\xff\x00\x00\x00\x01\x99')

    device.char_write.side_effect = send_response

    state = light.get_state()
    assert state.is_on is False
    assert state.color == (255, 0, 0)
    device.char_write.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb', b'\xEF\x01\x77')
    assert state.__repr__() == "<LightState is_on='False' color='(255, 0, 0)'>"

    # Ensure duplicate responses are handled
    def send_response(*args, **kwargs):
        """Simulate a response from the light"""
        light._handle_data(
            63, b'\x66\xe3\x23\x16\x24\x01\x10\x05\x1C\x00\x01\x99')
        light._handle_data(
            63, b'\x66\xe3\x23\x16\x24\x01\x10\x05\x1C\x00\x01\x99')

    device.char_write.side_effect = send_response

    state = light.get_state()
    assert state.is_on is True
    assert state.color == (131, 41, 230)
    device.char_write.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb', b'\xEF\x01\x77')

    # Ensure leftover values are discarded before querying
    def send_response(*args, **kwargs):
        """Simulate a response from the light"""
        light._handle_data(
            63, b'\x66\xe3\x00\x16\x24\x01\xFF\xFF\xFF\x00\x01\x99')

    device.char_write.side_effect = send_response

    state = light.get_state()
    assert state.is_on is None
    assert state.color == (255, 255, 255)
    device.char_write.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb', b'\xEF\x01\x77')

    # Test response timeout
    device.char_write.side_effect = None
    light.notification_queue = mocker.MagicMock()

    def get_queue(*args, **kwargs):
        """Simulate a queue timeout"""
        raise queue.Empty()

    light.notification_queue.get.side_effect = get_queue

    with pytest.raises(TimeoutError):
        state = light.get_state()
Пример #9
0
def test_connect_disconnect(adapter, device):
    """Test the CLI."""
    light = Light("00:11:22")
    light.connect()

    adapter.start.assert_called_with(reset_on_start=False)
    adapter.connect.assert_called_with("00:11:22", auto_reconnect=False)
    device.subscribe.assert_called_with("0000ffe4-0000-1000-8000-00805f9b34fb",
                                        callback=light._handle_data)

    light.disconnect()

    adapter.stop.assert_called_once()

    # Duplicate disconnect shouldn't call stop again
    light.disconnect()

    adapter.stop.assert_called_once()

    # Test auto reconnect
    light = Light("00:11:22")
    light.connect(auto_reconnect=True)

    adapter.start.assert_called_with(reset_on_start=False)
    adapter.connect.assert_called_with("00:11:22", auto_reconnect=True)
Пример #10
0
def test_set_color(device):
    """Test the CLI."""
    light = Light("00:11:22")
    light.connect()

    light.set_color(255, 255, 255)
    device.char_write.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb',
        b'\x56\xFF\xFF\xFF\x00\xF0\xAA')

    light.set_color(64, 128, 192)
    device.char_write.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb',
        b'\x56\x08\x10\x18\x00\xF0\xAA')

    # Assert that lights are always on unless zero
    light.set_color(1, 1, 1)
    device.char_write.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb',
        b'\x56\x01\x01\x01\x00\xF0\xAA')

    # When called with all zeros, just turn off the light
    light.set_color(0, 0, 0)
    device.char_write.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb', b'\xCC\x24\x33')

    with pytest.raises(ValueError):
        light.set_color(999, 999, 999)
Пример #11
0
def test_turn_on_not_connected(device):
    """Test the CLI."""
    light = Light("00:11:22")

    with pytest.raises(RuntimeError):
        light.turn_on()
Пример #12
0
def test_exception_wrapping(device, adapter):
    """Test the CLI."""
    def raise_exception(*args, **kwargs):
        raise pygatt.BLEError("TEST")

    adapter.start.side_effect = raise_exception

    with pytest.raises(ZerprocException):
        light = Light("00:11:22")
        light.connect()

    adapter.start.side_effect = None
    adapter.stop.side_effect = raise_exception

    with pytest.raises(ZerprocException):
        light = Light("00:11:22")
        light.connect()
        light.disconnect()

    device.char_write.side_effect = raise_exception

    with pytest.raises(ZerprocException):
        light = Light("00:11:22")
        light.connect()
        light.turn_on()
Пример #13
0
async def test_get_state(client):
    """Test getting the light state."""
    light = Light("00:11:22")
    await light.connect()

    async def send_response(*args, **kwargs):
        """Simulate a response from the light"""
        light._handle_data(
            63, b'\x66\xe3\x24\x16\x24\x01\xff\x00\x00\x00\x01\x99')

    client.write_gatt_char.side_effect = send_response

    state = await light.get_state()
    assert state.is_on is False
    assert state.color == (255, 0, 0)
    client.write_gatt_char.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb', b'\xEF\x01\x77')
    assert state.__repr__() == "<LightState is_on='False' color='(255, 0, 0)'>"

    # Ensure duplicate responses are handled
    async def send_response(*args, **kwargs):
        """Simulate a response from the light"""
        light._handle_data(
            63, b'\x66\xe3\x23\x16\x24\x01\x10\x05\x1C\x00\x01\x99')
        light._handle_data(
            63, b'\x66\xe3\x23\x16\x24\x01\x10\x05\x1C\x00\x01\x99')

    client.write_gatt_char.side_effect = send_response

    state = await light.get_state()
    assert state.is_on is True
    assert state.color == (131, 41, 230)
    client.write_gatt_char.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb', b'\xEF\x01\x77')

    # Ensure leftover values are discarded before querying
    async def send_response(*args, **kwargs):
        """Simulate a response from the light"""
        light._handle_data(
            63, b'\x66\xe3\x00\x16\x24\x01\xFF\xFF\xFF\x00\x01\x99')

    client.write_gatt_char.side_effect = send_response

    state = await light.get_state()
    assert state.is_on is None
    assert state.color == (255, 255, 255)
    client.write_gatt_char.assert_called_with(
        '0000ffe9-0000-1000-8000-00805f9b34fb', b'\xEF\x01\x77')

    # Test response timeout
    client.write_gatt_char.side_effect = None
    light._notification_queue = MagicMock()

    async def get_queue(*args, **kwargs):
        """Simulate a queue timeout"""
        raise asyncio.TimeoutError()

    light._notification_queue.get.side_effect = get_queue

    with pytest.raises(ZerprocException):
        state = await light.get_state()