docs: def get_blackbird(url, use_serial=True):
      """
      Return synchronous version of Blackbird interface
      :param port_url: serial port, i.e. '/dev/ttyUSB0'
      :return: synchronous implementation of Blackbird interface
      """
      lock = RLock()
      print(serial)
  
      def synchronized(func):
          @wraps(func)
          def wrapper(*args, **kwargs):
              with lock:
                  return func(*args, **kwargs)
          return wrapper
  
      class BlackbirdSync(Blackbird):
          def __init__(self, url):
              """
              Initialize the client.
              """
              if use_serial:
                  self._port = serial.serial_for_url(url, do_not_open=True)
                  self._port.baudrate = 9600
                  self._port.stopbits = serial.STOPBITS_ONE
                  self._port.bytesize = serial.EIGHTBITS
                  self._port.parity = serial.PARITY_NONE
                  self._port.timeout = TIMEOUT
                  self._port.write_timeout = TIMEOUT
                  self._port.open()
  
              else:
                  self.host = url
                  self.port = PORT
                  self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                  self.socket.settimeout(TIMEOUT)
                  self.socket.connect((self.host, self.port))
  
                  # Clear login message
                  self.socket.recv(SOCKET_RECV)
  
          def _process_request(self, request: bytes, skip=0):
              """
              Send data to socket
              :param request: request that is sent to the blackbird
              :param skip: number of bytes to skip for end of transmission decoding
              :return: ascii string returned by blackbird
              """
              _LOGGER.debug('Sending "%s"', request)
  
              if use_serial:
                  # clear
                  self._port.reset_output_buffer()
                  self._port.reset_input_buffer()
                  # send
                  self._port.write(request)
                  self._port.flush()
                  # receive
                  result = bytearray()
                  while True:
                      c = self._port.read(1)
                      if c is None:
                          break
                      if not c:
                          raise serial.SerialTimeoutException(
                              'Connection timed out! Last received bytes {}'.format([hex(a) for a in result]))
                      result += c
                      if len(result) > skip and result [-LEN_EOL:] == EOL:
                          break
                  ret = bytes(result)
                  _LOGGER.debug('Received "%s"', ret)
                  return ret.decode('ascii')
  
              else:
                  self.socket.send(request)
  
                  response = ''
  
                  while True:
  
                      data = self.socket.recv(SOCKET_RECV)
                      response += data.decode('ascii')
                      
                      if EOL in data and len(response) > skip:
                          break
  
                  return response
  
          @synchronized
          def zone_status(self, zone: int):
              # Returns status of a zone
              return ZoneStatus.from_string(zone, self._process_request(_format_zone_status_request(zone), skip=20))
  
          @synchronized
          def set_zone_power(self, zone: int, power: bool):
              # Set zone power
              self._process_request(_format_set_zone_power(zone, power))
  
          @synchronized
          def set_zone_source(self, zone: int, source: int):
              # Set zone source
              self._process_request(_format_set_zone_source(zone, source))
  
          @synchronized
          def set_all_zone_source(self, source: int):
              # Set all zones to one source
              self._process_request(_format_set_all_zone_source(source))
  
          @synchronized
          def lock_front_buttons(self):
              # Lock front panel buttons
              self._process_request(_format_lock_front_buttons())
  
          @synchronized
          def unlock_front_buttons(self):
              # Unlock front panel buttons
              self._process_request(_format_unlock_front_buttons())
  
          @synchronized
          def lock_status(self):
              # Report system locking status
              return LockStatus.from_string(self._process_request(_format_lock_status()))
  
      return BlackbirdSync(url)