docs: def send_tunnelling_request(self, cemi, auto_connect=True):
          """Sends a tunneling request based on the given CEMI data.
  
          This method does not wait for an acknowledge or result frame.
          """
          if not self.connected:
              if auto_connect:
                  if not self.connect():
                      raise KNXException("KNX tunnel not reconnected")
              else:
                  raise KNXException("KNX tunnel not connected")
  
          frame = KNXIPFrame(KNXIPFrame.TUNNELING_REQUEST)
          # Connection header see KNXnet/IP 4.4.6 TUNNELLING_REQUEST
          body = [0x04, self.channel, self.seq, 0x00]
          if self.seq < 0xff:
              self.seq += 1
          else:
              self.seq = 0
          body.extend(cemi.to_body())
          frame.body = body
          self.data_server.socket.sendto(
              frame.to_frame(), (self.remote_ip, self.remote_port))
  
          # See KNX specification 3.8.4 chapter 2.6 "Frame confirmation"
          # Send KNX packet 2 times if not acknowledged and close
          # the connection if no ack is received
          res = self.ack_semaphore.acquire(blocking=True, timeout=1)
          # Resend package if not acknowledged after 1 seconds
          if not res:
              self.data_server.socket.sendto(
                  frame.to_frame(), (self.remote_ip, self.remote_port))
  
              res = self.ack_semaphore.acquire(blocking=True, timeout=1)
  
          # disconnect and reconnect of not acknowledged
          if not res:
              self.disconnect()
              self.connect()
  
          return res