Return asynchronous version of Blackbird interface
    :param port_url: serial port, i.e. '/dev/ttyUSB0'
    :return: asynchronous implementation of Blackbird interface

def get_async_blackbird(port_url, loop):
    """
    Return asynchronous version of Blackbird interface
    :param port_url: serial port, i.e. '/dev/ttyUSB0'
    :return: asynchronous implementation of Blackbird interface
    """

    lock = asyncio.Lock()

    def locked_coro(coro):
        @asyncio.coroutine
        @wraps(coro)
        def wrapper(*args, **kwargs):
            with (yield from lock):
                return (yield from coro(*args, **kwargs))
        return wrapper

    class BlackbirdAsync(Blackbird):
        def __init__(self, blackbird_protocol):
            self._protocol = blackbird_protocol

        @locked_coro
        @asyncio.coroutine
        def zone_status(self, zone: int):
            string = yield from self._protocol.send(_format_zone_status_request(zone), skip=15)
            return ZoneStatus.from_string(zone, string)

        @locked_coro
        @asyncio.coroutine
        def set_zone_power(self, zone: int, power: bool):
            yield from self._protocol.send(_format_set_zone_power(zone, power))

        @locked_coro
        @asyncio.coroutine
        def set_zone_source(self, zone: int, source: int):
            yield from self._protocol.send(_format_set_zone_source(zone, source))

        @locked_coro
        @asyncio.coroutine
        def set_all_zone_source(self, source: int):
            yield from self._protocol.send(_format_set_all_zone_source(source))

        @locked_coro
        @asyncio.coroutine
        def lock_front_buttons(self):
            yield from self._protocol.send(_format_lock_front_buttons())

        @locked_coro
        @asyncio.coroutine
        def unlock_front_buttons(self):
            yield from self._protocol.send(_format_unlock_front_buttons())

        @locked_coro
        @asyncio.coroutine
        def lock_status(self):
            string = yield from self._protocol.send(_format_lock_status())
            return LockStatus.from_string(string)

    class BlackbirdProtocol(asyncio.Protocol):
        def __init__(self, loop):
            super().__init__()
            self._loop = loop
            self._lock = asyncio.Lock()
            self._transport = None
            self._connected = asyncio.Event(loop=loop)
            self.q = asyncio.Queue(loop=loop)

        def connection_made(self, transport):
            self._transport = transport
            self._connected.set()
            _LOGGER.debug('port opened %s', self._transport)

        def data_received(self, data):
            asyncio.ensure_future(self.q.put(data), loop=self._loop)

        @asyncio.coroutine
        def send(self, request: bytes, skip=0):
            yield from self._connected.wait()
            result = bytearray()
            # Only one transaction at a time
            with (yield from self._lock):
                self._transport.serial.reset_output_buffer()
                self._transport.serial.reset_input_buffer()
                while not self.q.empty():
                    self.q.get_nowait()
                self._transport.write(request)
                try:
                    while True:
                        result += yield from asyncio.wait_for(self.q.get(), TIMEOUT, loop=self._loop)
                        if len(result) > skip and result[-LEN_EOL:] == EOL:
                            ret = bytes(result)
                            _LOGGER.debug('Received "%s"', ret)
                            return ret.decode('ascii')
                except asyncio.TimeoutError:
                    _LOGGER.error("Timeout during receiving response for command '%s', received='%s'", request, result)
                    raise

    _, protocol = yield from create_serial_connection(loop, functools.partial(BlackbirdProtocol, loop), port_url, baudrate=9600)

    return BlackbirdAsync(protocol)